refactor metrics defaultCollector&&agg (#12206)
* remove unused generic * use request event * fix test * add licence * bugfix * code opt * code opt * code opt * code opt * code opt * code opt * fix ci * fix * revert * opt * opt * bugfix --------- Co-authored-by: x-shadow-man <1494445739@qq.com>
This commit is contained in:
parent
d711c0ca85
commit
acd4212f59
|
|
@ -20,7 +20,8 @@ package org.apache.dubbo.rpc.cluster.filter.support;
|
|||
|
||||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.event.RequestBeforeEvent;
|
||||
import org.apache.dubbo.rpc.BaseFilter;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
|
|
@ -30,19 +31,17 @@ import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
|
|||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.ScopeModelAware;
|
||||
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
|
||||
|
||||
@Activate(group = CONSUMER,onClass = "org.apache.dubbo.metrics.collector.DefaultMetricsCollector")
|
||||
@Activate(group = CONSUMER, onClass = "org.apache.dubbo.metrics.collector.DefaultMetricsCollector")
|
||||
public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener, ScopeModelAware {
|
||||
|
||||
private ApplicationModel applicationModel;
|
||||
private DefaultMetricsCollector collector;
|
||||
|
||||
@Override
|
||||
public void setApplicationModel(ApplicationModel applicationModel) {
|
||||
this.applicationModel = applicationModel;
|
||||
this.collector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
|
||||
}
|
||||
|
||||
|
|
@ -65,18 +64,12 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener,
|
|||
if (collector == null || !collector.isCollectEnabled()) {
|
||||
return;
|
||||
}
|
||||
if (t != null && t instanceof RpcException) {
|
||||
if (t instanceof RpcException) {
|
||||
RpcException e = (RpcException) t;
|
||||
if (e.isForbidden()) {
|
||||
collector.getMethodSampler().incOnEvent(invocation,
|
||||
MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(getSide(invocation)));
|
||||
MetricsEventBus.publish(RequestBeforeEvent.toEvent(applicationModel, invocation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getSide(Invocation invocation) {
|
||||
Optional<? extends Invoker<?>> invoker = Optional.ofNullable(invocation.getInvoker());
|
||||
String side = invoker.isPresent() ? invoker.get().getUrl().getSide() : PROVIDER_SIDE;
|
||||
return side;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,23 +15,17 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.metrics.metrics.event;
|
||||
package org.apache.dubbo.common.lang;
|
||||
|
||||
import org.apache.dubbo.metrics.event.RTEvent;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
class RTEventTest {
|
||||
|
||||
@Test
|
||||
void testNewEvent() {
|
||||
MethodMetric metric = new MethodMetric();
|
||||
Long rt = 5L;
|
||||
RTEvent event = new RTEvent(ApplicationModel.defaultModel(), metric, rt);
|
||||
|
||||
Assertions.assertEquals(event.getSource(), ApplicationModel.defaultModel());
|
||||
Assertions.assertEquals(event.getRt(), rt);
|
||||
}
|
||||
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Nullable {
|
||||
}
|
||||
|
|
@ -18,7 +18,12 @@ package org.apache.dubbo.common.utils;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A utility class that provides methods for accessing and manipulating private fields and methods of an object.
|
||||
|
|
@ -28,7 +33,8 @@ import java.util.Arrays;
|
|||
*/
|
||||
public class ReflectionUtils {
|
||||
|
||||
private ReflectionUtils(){}
|
||||
private ReflectionUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified field from the given object.
|
||||
|
|
@ -92,7 +98,50 @@ public class ReflectionUtils {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static class ReflectionException extends RuntimeException{
|
||||
/**
|
||||
* Returns a list of distinct {@link Class} objects representing the generics of the given class that implement the
|
||||
* given interface.
|
||||
*
|
||||
* @param clazz the class to retrieve the generics for
|
||||
* @param interfaceClass the interface to retrieve the generics for
|
||||
* @return a list of distinct {@link Class} objects representing the generics of the given class that implement the
|
||||
* given interface
|
||||
*/
|
||||
public static List<Class<?>> getClassGenerics(Class<?> clazz, Class<?> interfaceClass) {
|
||||
List<Class<?>> generics = new ArrayList<>();
|
||||
Type[] genericInterfaces = clazz.getGenericInterfaces();
|
||||
for (Type genericInterface : genericInterfaces) {
|
||||
if (genericInterface instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
|
||||
Type rawType = parameterizedType.getRawType();
|
||||
if (rawType instanceof Class && interfaceClass.isAssignableFrom((Class<?>) rawType)) {
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
for (Type actualTypeArgument : actualTypeArguments) {
|
||||
if (actualTypeArgument instanceof Class) {
|
||||
generics.add((Class<?>) actualTypeArgument);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Type genericSuperclass = clazz.getGenericSuperclass();
|
||||
if (genericSuperclass instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
for (Type actualTypeArgument : actualTypeArguments) {
|
||||
if (actualTypeArgument instanceof Class) {
|
||||
generics.add((Class<?>) actualTypeArgument);
|
||||
}
|
||||
}
|
||||
}
|
||||
Class<?> superclass = clazz.getSuperclass();
|
||||
if (superclass != null) {
|
||||
generics.addAll(getClassGenerics(superclass, interfaceClass));
|
||||
}
|
||||
return generics.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static class ReflectionException extends RuntimeException {
|
||||
public ReflectionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ package org.apache.dubbo.metrics;
|
|||
|
||||
public interface MetricsConstants {
|
||||
|
||||
String INVOCATION = "metric_filter_invocation";
|
||||
String INVOCATION_METRICS_COUNTER = "metric_filter_invocation_counter";
|
||||
|
||||
String INVOCATION_SIDE = "metric_filter_side";
|
||||
|
||||
String ATTACHMENT_KEY_SERVICE = "serviceKey";
|
||||
String ATTACHMENT_KEY_SIZE = "size";
|
||||
String ATTACHMENT_KEY_LAST_NUM_MAP = "lastNumMap";
|
||||
|
|
|
|||
|
|
@ -20,15 +20,18 @@ package org.apache.dubbo.metrics.collector;
|
|||
import org.apache.dubbo.metrics.data.BaseStatComposite;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsListener;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE;
|
||||
|
||||
public abstract class CombMetricsCollector<E extends TimeCounterEvent> implements ApplicationMetricsCollector<E>, ServiceMetricsCollector<E> {
|
||||
public abstract class CombMetricsCollector<E extends TimeCounterEvent> extends AbstractMetricsListener<E> implements ApplicationMetricsCollector<E>, ServiceMetricsCollector<E>, MethodMetricsCollector<E> {
|
||||
|
||||
private final BaseStatComposite stats;
|
||||
private MetricsEventMulticaster eventMulticaster;
|
||||
|
|
@ -43,7 +46,7 @@ public abstract class CombMetricsCollector<E extends TimeCounterEvent> implement
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setNum(MetricsKey metricsKey, String applicationName, String serviceKey, int num) {
|
||||
public void setNum(MetricsKeyWrapper metricsKey, String applicationName, String serviceKey, int num) {
|
||||
this.stats.setServiceKey(metricsKey, applicationName, serviceKey, num);
|
||||
}
|
||||
|
||||
|
|
@ -52,8 +55,8 @@ public abstract class CombMetricsCollector<E extends TimeCounterEvent> implement
|
|||
this.stats.incrementApp(metricsKey, applicationName, SELF_INCREMENT_SIZE);
|
||||
}
|
||||
|
||||
public void increment(String applicationName, String serviceKey, MetricsKey metricsKey, int size) {
|
||||
this.stats.incrementServiceKey(metricsKey, applicationName, serviceKey, size);
|
||||
public void increment(String applicationName, String serviceKey, MetricsKeyWrapper metricsKeyWrapper, int size) {
|
||||
this.stats.incrementServiceKey(metricsKeyWrapper, applicationName, serviceKey, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -65,11 +68,24 @@ public abstract class CombMetricsCollector<E extends TimeCounterEvent> implement
|
|||
stats.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
protected List<GaugeMetricSample> export(MetricsCategory category) {
|
||||
@Override
|
||||
public void increment(String applicationName, Invocation invocation, MetricsKeyWrapper wrapper, int size) {
|
||||
this.stats.incrementMethodKey(wrapper, applicationName, invocation, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime) {
|
||||
stats.calcMethodKeyRt(applicationName, invocation, registryOpType, responseTime);
|
||||
}
|
||||
|
||||
protected List<MetricSample> export(MetricsCategory category) {
|
||||
return stats.export(category);
|
||||
}
|
||||
|
||||
public MetricsEventMulticaster getEventMulticaster() {
|
||||
return eventMulticaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(TimeCounterEvent event) {
|
||||
eventMulticaster.publishEvent(event);
|
||||
|
|
|
|||
|
|
@ -15,33 +15,19 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.metrics.event;
|
||||
package org.apache.dubbo.metrics.collector;
|
||||
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
||||
/**
|
||||
* RtEvent.
|
||||
* Method-level metrics collection for rpc invocation scenarios
|
||||
*/
|
||||
public class RTEvent extends MetricsEvent {
|
||||
private Long rt;
|
||||
private final Object metric;
|
||||
public interface MethodMetricsCollector<E extends TimeCounterEvent> extends MetricsCollector<E> {
|
||||
|
||||
public RTEvent(ApplicationModel applicationModel, Object metric, Long rt) {
|
||||
super(applicationModel);
|
||||
this.rt = rt;
|
||||
this.metric = metric;
|
||||
setAvailable(true);
|
||||
}
|
||||
void increment(String applicationName, Invocation invocation, MetricsKeyWrapper wrapper, int size);
|
||||
|
||||
public Long getRt() {
|
||||
return rt;
|
||||
}
|
||||
|
||||
public void setRt(Long rt) {
|
||||
this.rt = rt;
|
||||
}
|
||||
|
||||
public Object getMetric() {
|
||||
return metric;
|
||||
}
|
||||
void addRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime);
|
||||
}
|
||||
|
||||
|
|
@ -18,19 +18,17 @@
|
|||
package org.apache.dubbo.metrics.collector;
|
||||
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
|
||||
/**
|
||||
* Application-level collector.
|
||||
* Service-level collector.
|
||||
* registration center, configuration center and other scenarios
|
||||
*
|
||||
* @Params <T> metrics type
|
||||
*/
|
||||
public interface ServiceMetricsCollector<E extends TimeCounterEvent> extends MetricsCollector<E> {
|
||||
|
||||
void increment(String applicationName, String serviceKey, MetricsKey metricsKey, int size);
|
||||
void increment(String applicationName, String serviceKey, MetricsKeyWrapper wrapper, int size);
|
||||
|
||||
void setNum(MetricsKey metricsKey, String applicationName, String serviceKey, int num);
|
||||
void setNum(MetricsKeyWrapper metricsKey, String applicationName, String serviceKey, int num);
|
||||
|
||||
void addRt(String applicationName, String serviceKey, String registryOpType, Long responseTime);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import org.apache.dubbo.metrics.model.MetricsCategory;
|
|||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.report.MetricsExport;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -48,17 +49,9 @@ public class ApplicationStatComposite implements MetricsExport {
|
|||
applicationNumStats.get(metricsKey).computeIfAbsent(applicationName, k -> new AtomicLong(0L)).getAndAdd(size);
|
||||
}
|
||||
|
||||
public void setApplicationKey(MetricsKey metricsKey, String applicationName, int num) {
|
||||
if (!applicationNumStats.containsKey(metricsKey)) {
|
||||
return;
|
||||
}
|
||||
applicationNumStats.get(metricsKey).computeIfAbsent(applicationName, k -> new AtomicLong(0L)).set(num);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public List<GaugeMetricSample> export(MetricsCategory category) {
|
||||
List<GaugeMetricSample> list = new ArrayList<>();
|
||||
public List<MetricSample> export(MetricsCategory category) {
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
for (MetricsKey type : applicationNumStats.keySet()) {
|
||||
Map<String, AtomicLong> stringAtomicLongMap = applicationNumStats.get(type);
|
||||
for (String applicationName : stringAtomicLongMap.keySet()) {
|
||||
|
|
|
|||
|
|
@ -20,9 +20,10 @@ package org.apache.dubbo.metrics.data;
|
|||
import org.apache.dubbo.metrics.collector.MetricsCollector;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.report.MetricsExport;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -37,14 +38,31 @@ public abstract class BaseStatComposite implements MetricsExport {
|
|||
|
||||
private final ApplicationStatComposite applicationStatComposite = new ApplicationStatComposite();
|
||||
private final ServiceStatComposite serviceStatComposite = new ServiceStatComposite();
|
||||
|
||||
private final MethodStatComposite methodStatComposite = new MethodStatComposite();
|
||||
private final RtStatComposite rtStatComposite = new RtStatComposite();
|
||||
|
||||
|
||||
public BaseStatComposite() {
|
||||
init(applicationStatComposite, serviceStatComposite, rtStatComposite);
|
||||
init(applicationStatComposite);
|
||||
init(serviceStatComposite);
|
||||
init(methodStatComposite);
|
||||
init(rtStatComposite);
|
||||
}
|
||||
|
||||
protected abstract void init(ApplicationStatComposite applicationStatComposite, ServiceStatComposite serviceStatComposite, RtStatComposite rtStatComposite);
|
||||
|
||||
protected void init(ApplicationStatComposite applicationStatComposite) {
|
||||
}
|
||||
|
||||
protected void init(ServiceStatComposite serviceStatComposite) {
|
||||
|
||||
}
|
||||
|
||||
protected void init(MethodStatComposite methodStatComposite) {
|
||||
}
|
||||
|
||||
protected void init(RtStatComposite rtStatComposite) {
|
||||
}
|
||||
|
||||
public void calcApplicationRt(String applicationName, String registryOpType, Long responseTime) {
|
||||
rtStatComposite.calcApplicationRt(applicationName, registryOpType, responseTime);
|
||||
|
|
@ -54,29 +72,33 @@ public abstract class BaseStatComposite implements MetricsExport {
|
|||
rtStatComposite.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime);
|
||||
}
|
||||
|
||||
public void setServiceKey(MetricsKey metricsKey, String applicationName, String serviceKey, int num) {
|
||||
serviceStatComposite.setServiceKey(metricsKey, applicationName, serviceKey, num);
|
||||
public void calcMethodKeyRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime) {
|
||||
rtStatComposite.calcMethodKeyRt(applicationName, invocation, registryOpType, responseTime);
|
||||
}
|
||||
|
||||
public void setApplicationKey(MetricsKey metricsKey, String applicationName, int num) {
|
||||
applicationStatComposite.setApplicationKey(metricsKey, applicationName, num);
|
||||
public void setServiceKey(MetricsKeyWrapper metricsKey, String applicationName, String serviceKey, int num) {
|
||||
serviceStatComposite.setServiceKey(metricsKey, applicationName, serviceKey, num);
|
||||
}
|
||||
|
||||
public void incrementApp(MetricsKey metricsKey, String applicationName, int size) {
|
||||
applicationStatComposite.incrementSize(metricsKey, applicationName, size);
|
||||
}
|
||||
|
||||
public void incrementServiceKey(MetricsKey metricsKey, String applicationName, String attServiceKey, int size) {
|
||||
serviceStatComposite.incrementServiceKey(metricsKey, applicationName, attServiceKey, size);
|
||||
public void incrementServiceKey(MetricsKeyWrapper metricsKeyWrapper, String applicationName, String attServiceKey, int size) {
|
||||
serviceStatComposite.incrementServiceKey(metricsKeyWrapper, applicationName, attServiceKey, size);
|
||||
}
|
||||
|
||||
public void incrementMethodKey(MetricsKeyWrapper metricsKeyWrapper, String applicationName, Invocation invocation, int size) {
|
||||
methodStatComposite.incrementMethodKey(metricsKeyWrapper, applicationName, invocation, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public List<GaugeMetricSample> export(MetricsCategory category) {
|
||||
List<GaugeMetricSample> list = new ArrayList<>();
|
||||
public List<MetricSample> export(MetricsCategory category) {
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
list.addAll(applicationStatComposite.export(category));
|
||||
list.addAll(rtStatComposite.export(category));
|
||||
list.addAll(serviceStatComposite.export(category));
|
||||
list.addAll(methodStatComposite.export(category));
|
||||
return list;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.data;
|
||||
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.report.MetricsExport;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class MethodStatComposite implements MetricsExport {
|
||||
|
||||
private final Map<MetricsKeyWrapper, Map<MethodMetric, AtomicLong>> methodNumStats = new ConcurrentHashMap<>();
|
||||
|
||||
public void initWrapper(List<MetricsKeyWrapper> metricsKeyWrappers) {
|
||||
if (CollectionUtils.isEmpty(metricsKeyWrappers)) {
|
||||
return;
|
||||
}
|
||||
metricsKeyWrappers.forEach(appKey -> methodNumStats.put(appKey, new ConcurrentHashMap<>()));
|
||||
}
|
||||
|
||||
public void incrementMethodKey(MetricsKeyWrapper wrapper, String applicationName, Invocation invocation, int size) {
|
||||
if (!methodNumStats.containsKey(wrapper)) {
|
||||
return;
|
||||
}
|
||||
methodNumStats.get(wrapper).computeIfAbsent(new MethodMetric(applicationName, invocation), k -> new AtomicLong(0L)).getAndAdd(size);
|
||||
}
|
||||
|
||||
public List<MetricSample> export(MetricsCategory category) {
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
for (MetricsKeyWrapper wrapper : methodNumStats.keySet()) {
|
||||
Map<MethodMetric, AtomicLong> stringAtomicLongMap = methodNumStats.get(wrapper);
|
||||
for (MethodMetric methodMetric : stringAtomicLongMap.keySet()) {
|
||||
if (methodMetric.getSampleType() == MetricSample.Type.GAUGE) {
|
||||
list.add(new CounterMetricSample<>(wrapper,
|
||||
methodMetric.getTags(), category, stringAtomicLongMap.get(methodMetric)));
|
||||
} else {
|
||||
list.add(new GaugeMetricSample<>(wrapper, methodMetric.getTags(), category, stringAtomicLongMap, value -> value.get(methodMetric).get()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -24,9 +24,11 @@ import org.apache.dubbo.metrics.model.container.AtomicLongContainer;
|
|||
import org.apache.dubbo.metrics.model.container.LongAccumulatorContainer;
|
||||
import org.apache.dubbo.metrics.model.container.LongContainer;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceType;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.report.MetricsExport;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -36,18 +38,19 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
import java.util.concurrent.atomic.LongAccumulator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public class RtStatComposite implements MetricsExport {
|
||||
|
||||
private final List<LongContainer<? extends Number>> rtStats = new ArrayList<>();
|
||||
|
||||
public void init(MetricsPlaceType... placeValues) {
|
||||
public void init(MetricsPlaceValue... placeValues) {
|
||||
if (placeValues == null) {
|
||||
return;
|
||||
}
|
||||
Arrays.stream(placeValues).forEach(metricsPlaceType -> rtStats.addAll(initStats(metricsPlaceType)));
|
||||
}
|
||||
|
||||
private List<LongContainer<? extends Number>> initStats(MetricsPlaceType placeValue) {
|
||||
private List<LongContainer<? extends Number>> initStats(MetricsPlaceValue placeValue) {
|
||||
List<LongContainer<? extends Number>> singleRtStats = new ArrayList<>();
|
||||
singleRtStats.add(new AtomicLongContainer(new MetricsKeyWrapper(MetricsKey.METRIC_RT_LAST, placeValue)));
|
||||
singleRtStats.add(new LongAccumulatorContainer(new MetricsKeyWrapper(MetricsKey.METRIC_RT_MIN, placeValue), new LongAccumulator(Long::min, Long.MAX_VALUE)));
|
||||
|
|
@ -65,7 +68,6 @@ public class RtStatComposite implements MetricsExport {
|
|||
return singleRtStats;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void calcApplicationRt(String applicationName, String registryOpType, Long responseTime) {
|
||||
for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
|
||||
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, applicationName, container.getInitFunc());
|
||||
|
|
@ -73,7 +75,6 @@ public class RtStatComposite implements MetricsExport {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void calcServiceKeyRt(String applicationName, String serviceKey, String registryOpType, Long responseTime) {
|
||||
for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
|
||||
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, applicationName + "_" + serviceKey, container.getInitFunc());
|
||||
|
|
@ -81,9 +82,15 @@ public class RtStatComposite implements MetricsExport {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public List<GaugeMetricSample> export(MetricsCategory category) {
|
||||
List<GaugeMetricSample> list = new ArrayList<>();
|
||||
public void calcMethodKeyRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime) {
|
||||
for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
|
||||
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, applicationName + "_" + invocation.getServiceName() + "_" + invocation.getMethodName(), container.getInitFunc());
|
||||
container.getConsumerFunc().accept(responseTime, current);
|
||||
}
|
||||
}
|
||||
|
||||
public List<MetricSample> export(MetricsCategory category) {
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
for (LongContainer<? extends Number> rtContainer : rtStats) {
|
||||
MetricsKeyWrapper metricsKeyWrapper = rtContainer.getMetricsKeyWrapper();
|
||||
for (Map.Entry<String, ? extends Number> entry : rtContainer.entrySet()) {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ package org.apache.dubbo.metrics.data;
|
|||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.ServiceKeyMetric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.report.MetricsExport;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -32,36 +33,35 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
|
||||
public class ServiceStatComposite implements MetricsExport {
|
||||
|
||||
private final Map<MetricsKey, Map<ServiceKeyMetric, AtomicLong>> serviceNumStats = new ConcurrentHashMap<>();
|
||||
private final Map<MetricsKeyWrapper, Map<ServiceKeyMetric, AtomicLong>> serviceWrapperNumStats = new ConcurrentHashMap<>();
|
||||
|
||||
public void init(List<MetricsKey> serviceKeys) {
|
||||
if (CollectionUtils.isEmpty(serviceKeys)) {
|
||||
public void initWrapper(List<MetricsKeyWrapper> metricsKeyWrappers) {
|
||||
if (CollectionUtils.isEmpty(metricsKeyWrappers)) {
|
||||
return;
|
||||
}
|
||||
serviceKeys.forEach(appKey -> serviceNumStats.put(appKey, new ConcurrentHashMap<>()));
|
||||
metricsKeyWrappers.forEach(appKey -> serviceWrapperNumStats.put(appKey, new ConcurrentHashMap<>()));
|
||||
}
|
||||
|
||||
public void incrementServiceKey(MetricsKey metricsKey, String applicationName, String serviceKey, int size) {
|
||||
if (!serviceNumStats.containsKey(metricsKey)) {
|
||||
public void incrementServiceKey(MetricsKeyWrapper wrapper, String applicationName, String serviceKey, int size) {
|
||||
if (!serviceWrapperNumStats.containsKey(wrapper)) {
|
||||
return;
|
||||
}
|
||||
serviceNumStats.get(metricsKey).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).getAndAdd(size);
|
||||
serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).getAndAdd(size);
|
||||
}
|
||||
|
||||
public void setServiceKey(MetricsKey type, String applicationName, String serviceKey, int num) {
|
||||
if (!serviceNumStats.containsKey(type)) {
|
||||
public void setServiceKey(MetricsKeyWrapper wrapper, String applicationName, String serviceKey, int num) {
|
||||
if (!serviceWrapperNumStats.containsKey(wrapper)) {
|
||||
return;
|
||||
}
|
||||
serviceNumStats.get(type).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).set(num);
|
||||
serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).set(num);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public List<GaugeMetricSample> export(MetricsCategory category) {
|
||||
List<GaugeMetricSample> list = new ArrayList<>();
|
||||
for (MetricsKey type : serviceNumStats.keySet()) {
|
||||
Map<ServiceKeyMetric, AtomicLong> stringAtomicLongMap = serviceNumStats.get(type);
|
||||
public List<MetricSample> export(MetricsCategory category) {
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
for (MetricsKeyWrapper wrapper : serviceWrapperNumStats.keySet()) {
|
||||
Map<ServiceKeyMetric, AtomicLong> stringAtomicLongMap = serviceWrapperNumStats.get(wrapper);
|
||||
for (ServiceKeyMetric serviceKeyMetric : stringAtomicLongMap.keySet()) {
|
||||
list.add(new GaugeMetricSample<>(type, serviceKeyMetric.getTags(), category, stringAtomicLongMap, value -> value.get(serviceKeyMetric).get()));
|
||||
list.add(new GaugeMetricSample<>(wrapper, serviceKeyMetric.getTags(), category, stringAtomicLongMap, value -> value.get(serviceKeyMetric).get()));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public class EmptyEvent extends MetricsEvent {
|
|||
private static final EmptyEvent empty = new EmptyEvent(null);
|
||||
|
||||
private EmptyEvent(ApplicationModel source) {
|
||||
super(source);
|
||||
super(source, null);
|
||||
}
|
||||
|
||||
public static EmptyEvent instance() {
|
||||
|
|
|
|||
|
|
@ -1,47 +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.event;
|
||||
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
public class MethodEvent extends MetricsEvent {
|
||||
private String type;
|
||||
private final MethodMetric methodMetric;
|
||||
|
||||
public MethodEvent(ApplicationModel applicationModel, MethodMetric methodMetric, String type) {
|
||||
super(applicationModel);
|
||||
this.type = type;
|
||||
this.methodMetric = methodMetric;
|
||||
setAvailable(true);
|
||||
}
|
||||
|
||||
public MethodMetric getMethodMetric() {
|
||||
return methodMetric;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -35,11 +35,12 @@ public abstract class MetricsEvent {
|
|||
*/
|
||||
protected transient ApplicationModel source;
|
||||
private boolean available = true;
|
||||
protected TypeWrapper typeWrapper;
|
||||
private final TypeWrapper typeWrapper;
|
||||
|
||||
private final Map<String, Object> attachment = new HashMap<>(8);
|
||||
|
||||
public MetricsEvent(ApplicationModel source) {
|
||||
public MetricsEvent(ApplicationModel source, TypeWrapper typeWrapper) {
|
||||
this.typeWrapper = typeWrapper;
|
||||
if (source == null) {
|
||||
this.source = ApplicationModel.defaultModel();
|
||||
// Appears only in unit tests
|
||||
|
|
@ -51,8 +52,8 @@ public abstract class MetricsEvent {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getAttachmentValue(String key) {
|
||||
if (!attachment.containsKey(key)) {
|
||||
throw new MetricsNeverHappenException("Attachment key [" + key + "] not found");
|
||||
if (key == null) {
|
||||
throw new MetricsNeverHappenException("Attachment key is null");
|
||||
}
|
||||
return (T) attachment.get(key);
|
||||
}
|
||||
|
|
@ -82,6 +83,10 @@ public abstract class MetricsEvent {
|
|||
return getSource().getApplicationName();
|
||||
}
|
||||
|
||||
public TypeWrapper getTypeWrapper() {
|
||||
return typeWrapper;
|
||||
}
|
||||
|
||||
public boolean isAssignableFrom(Object type) {
|
||||
return typeWrapper.isAssignableFrom(type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,48 +73,77 @@ public class MetricsEventBus {
|
|||
* @return Biz result
|
||||
*/
|
||||
public static <T> T post(MetricsEvent event, Supplier<T> targetSupplier, Function<T, Boolean> trFunction) {
|
||||
if (event.getSource() == null) {
|
||||
return targetSupplier.get();
|
||||
}
|
||||
ApplicationModel applicationModel = event.getSource();
|
||||
if (applicationModel.isDestroyed()) {
|
||||
return targetSupplier.get();
|
||||
}
|
||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||
if (beanFactory.isDestroyed()) {
|
||||
return targetSupplier.get();
|
||||
}
|
||||
MetricsDispatcher dispatcher = beanFactory.getBean(MetricsDispatcher.class);
|
||||
if (dispatcher == null) {
|
||||
return targetSupplier.get();
|
||||
}
|
||||
dispatcher.publishEvent(event);
|
||||
if (!(event instanceof TimeCounterEvent)) {
|
||||
return targetSupplier.get();
|
||||
}
|
||||
TimeCounterEvent timeCounterEvent = (TimeCounterEvent) event;
|
||||
T result;
|
||||
before(event);
|
||||
if (trFunction == null) {
|
||||
try {
|
||||
result = targetSupplier.get();
|
||||
} catch (Throwable e) {
|
||||
dispatcher.publishErrorEvent(timeCounterEvent);
|
||||
error(event);
|
||||
throw e;
|
||||
}
|
||||
event.customAfterPost(result);
|
||||
dispatcher.publishFinishEvent(timeCounterEvent);
|
||||
after(event, result);
|
||||
} else {
|
||||
// Custom failure status
|
||||
result = targetSupplier.get();
|
||||
if (trFunction.apply(result)) {
|
||||
event.customAfterPost(result);
|
||||
dispatcher.publishFinishEvent(timeCounterEvent);
|
||||
after(event, result);
|
||||
} else {
|
||||
dispatcher.publishErrorEvent(timeCounterEvent);
|
||||
error(event);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void before(MetricsEvent event) {
|
||||
before(event, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applicable to the scene where execution and return are separated,
|
||||
* eventSaveRunner saves the event, so that the calculation rt is introverted
|
||||
*/
|
||||
public static void before(MetricsEvent event, Runnable eventSaveRunner) {
|
||||
MetricsDispatcher dispatcher = validate(event);
|
||||
if (dispatcher == null) return;
|
||||
dispatcher.publishEvent(event);
|
||||
if (eventSaveRunner != null) {
|
||||
eventSaveRunner.run();
|
||||
}
|
||||
}
|
||||
|
||||
public static void after(MetricsEvent event, Object result) {
|
||||
MetricsDispatcher dispatcher = validate(event);
|
||||
if (dispatcher == null) return;
|
||||
event.customAfterPost(result);
|
||||
dispatcher.publishFinishEvent((TimeCounterEvent) event);
|
||||
}
|
||||
|
||||
public static void error(MetricsEvent event) {
|
||||
MetricsDispatcher dispatcher = validate(event);
|
||||
if (dispatcher == null) return;
|
||||
dispatcher.publishErrorEvent((TimeCounterEvent) event);
|
||||
}
|
||||
|
||||
private static MetricsDispatcher validate(MetricsEvent event) {
|
||||
if (event.getSource() == null) {
|
||||
return null;
|
||||
}
|
||||
ApplicationModel applicationModel = event.getSource();
|
||||
if (applicationModel.isDestroyed()) {
|
||||
return null;
|
||||
}
|
||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||
if (beanFactory.isDestroyed()) {
|
||||
return null;
|
||||
}
|
||||
MetricsDispatcher dispatcher = beanFactory.getBean(MetricsDispatcher.class);
|
||||
if (dispatcher == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(event instanceof TimeCounterEvent)) {
|
||||
return null;
|
||||
}
|
||||
return dispatcher;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.dubbo.metrics.event;
|
||||
|
||||
import org.apache.dubbo.metrics.model.TimePair;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
/**
|
||||
|
|
@ -27,8 +28,8 @@ public abstract class TimeCounterEvent extends MetricsEvent {
|
|||
|
||||
private final TimePair timePair;
|
||||
|
||||
public TimeCounterEvent(ApplicationModel source) {
|
||||
super(source);
|
||||
public TimeCounterEvent(ApplicationModel source, TypeWrapper typeWrapper) {
|
||||
super(source, typeWrapper);
|
||||
this.timePair = TimePair.start();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.listener;
|
||||
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* According to the event template of {@link MetricsEventBus},
|
||||
* build a consistent static method for general and custom monitoring consume methods
|
||||
*/
|
||||
public abstract class AbstractMetricsKeyListener extends AbstractMetricsListener<TimeCounterEvent> implements MetricsLifeListener<TimeCounterEvent> {
|
||||
|
||||
private final MetricsKey metricsKey;
|
||||
|
||||
public AbstractMetricsKeyListener(MetricsKey metricsKey) {
|
||||
this.metricsKey = metricsKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* The MetricsKey type determines whether events are supported
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return super.isSupport(event) && event.isAssignableFrom(metricsKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(TimeCounterEvent event) {
|
||||
|
||||
}
|
||||
|
||||
public static AbstractMetricsKeyListener onEvent(MetricsKey metricsKey, Consumer<TimeCounterEvent> postFunc) {
|
||||
|
||||
return new AbstractMetricsKeyListener(metricsKey) {
|
||||
@Override
|
||||
public void onEvent(TimeCounterEvent event) {
|
||||
postFunc.accept(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static AbstractMetricsKeyListener onFinish(MetricsKey metricsKey, Consumer<TimeCounterEvent> finishFunc) {
|
||||
|
||||
return new AbstractMetricsKeyListener(metricsKey) {
|
||||
@Override
|
||||
public void onEventFinish(TimeCounterEvent event) {
|
||||
finishFunc.accept(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static AbstractMetricsKeyListener onError(MetricsKey metricsKey, Consumer<TimeCounterEvent> errorFunc) {
|
||||
|
||||
return new AbstractMetricsKeyListener(metricsKey) {
|
||||
@Override
|
||||
public void onEventError(TimeCounterEvent event) {
|
||||
errorFunc.accept(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -17,54 +17,21 @@
|
|||
|
||||
package org.apache.dubbo.metrics.listener;
|
||||
|
||||
import org.apache.dubbo.common.utils.ReflectionUtils;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractMetricsListener implements MetricsLifeListener<TimeCounterEvent> {
|
||||
public abstract class AbstractMetricsListener<E extends MetricsEvent> implements MetricsListener<E> {
|
||||
|
||||
private final MetricsKey metricsKey;
|
||||
|
||||
public AbstractMetricsListener(MetricsKey metricsKey) {
|
||||
this.metricsKey = metricsKey;
|
||||
/**
|
||||
* Whether to support the general determination of event points depends on the event type
|
||||
*/
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
List<Class<?>> eventTypes = ReflectionUtils.getClassGenerics(getClass(), AbstractMetricsListener.class);
|
||||
return event.isAvailable() && eventTypes.stream().allMatch(clazz -> clazz.isInstance(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event.isAvailable() && event.isAssignableFrom(metricsKey);
|
||||
}
|
||||
|
||||
public static AbstractMetricsListener onEvent(MetricsKey metricsKey, Consumer<TimeCounterEvent> postFunc) {
|
||||
|
||||
return new AbstractMetricsListener(metricsKey) {
|
||||
@Override
|
||||
public void onEvent(TimeCounterEvent event) {
|
||||
postFunc.accept(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static AbstractMetricsListener onFinish(MetricsKey metricsKey, Consumer<TimeCounterEvent> finishFunc) {
|
||||
|
||||
return new AbstractMetricsListener(metricsKey) {
|
||||
@Override
|
||||
public void onEventFinish(TimeCounterEvent event) {
|
||||
finishFunc.accept(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static AbstractMetricsListener onError(MetricsKey metricsKey, Consumer<TimeCounterEvent> errorFunc) {
|
||||
|
||||
return new AbstractMetricsListener(metricsKey) {
|
||||
@Override
|
||||
public void onEventError(TimeCounterEvent event) {
|
||||
errorFunc.accept(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public abstract void onEvent(E event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,24 +18,23 @@
|
|||
package org.apache.dubbo.metrics.listener;
|
||||
|
||||
import org.apache.dubbo.metrics.collector.CombMetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceType;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
|
||||
public class MetricsApplicationListener extends AbstractMetricsListener {
|
||||
public class MetricsApplicationListener extends AbstractMetricsKeyListener {
|
||||
|
||||
public MetricsApplicationListener(MetricsKey metricsKey) {
|
||||
super(metricsKey);
|
||||
}
|
||||
|
||||
public static AbstractMetricsListener onPostEventBuild(MetricsKey metricsKey, CombMetricsCollector<TimeCounterEvent> collector) {
|
||||
return AbstractMetricsListener.onEvent(metricsKey,
|
||||
public static AbstractMetricsKeyListener onPostEventBuild(MetricsKey metricsKey, CombMetricsCollector collector) {
|
||||
return AbstractMetricsKeyListener.onEvent(metricsKey,
|
||||
event -> collector.increment(event.appName(), metricsKey)
|
||||
);
|
||||
}
|
||||
|
||||
public static AbstractMetricsListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceType placeType, CombMetricsCollector<TimeCounterEvent> collector) {
|
||||
return AbstractMetricsListener.onFinish(metricsKey,
|
||||
public static AbstractMetricsKeyListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector collector) {
|
||||
return AbstractMetricsKeyListener.onFinish(metricsKey,
|
||||
event -> {
|
||||
collector.increment(event.appName(), metricsKey);
|
||||
collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc());
|
||||
|
|
@ -43,8 +42,8 @@ public class MetricsApplicationListener extends AbstractMetricsListener {
|
|||
);
|
||||
}
|
||||
|
||||
public static AbstractMetricsListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceType placeType, CombMetricsCollector<TimeCounterEvent> collector) {
|
||||
return AbstractMetricsListener.onError(metricsKey,
|
||||
public static AbstractMetricsKeyListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector collector) {
|
||||
return AbstractMetricsKeyListener.onError(metricsKey,
|
||||
event -> {
|
||||
collector.increment(event.appName(), metricsKey);
|
||||
collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc());
|
||||
|
|
|
|||
|
|
@ -19,21 +19,21 @@ package org.apache.dubbo.metrics.listener;
|
|||
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Metrics Listener.
|
||||
*/
|
||||
public interface MetricsListener<E extends MetricsEvent> {
|
||||
|
||||
default boolean isSupport(MetricsEvent event) {
|
||||
return event.isAvailable();
|
||||
}
|
||||
|
||||
boolean isSupport(MetricsEvent event);
|
||||
|
||||
/**
|
||||
* notify event.
|
||||
*
|
||||
* @param event BaseMetricsEvent
|
||||
*/
|
||||
default void onEvent(E event) {
|
||||
}
|
||||
void onEvent(E event);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,38 +19,32 @@ package org.apache.dubbo.metrics.listener;
|
|||
|
||||
import org.apache.dubbo.metrics.collector.ServiceMetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceType;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE;
|
||||
|
||||
public class MetricsServiceListener extends AbstractMetricsListener {
|
||||
public class MetricsServiceListener extends AbstractMetricsKeyListener {
|
||||
|
||||
public MetricsServiceListener(MetricsKey metricsKey) {
|
||||
super(metricsKey);
|
||||
}
|
||||
|
||||
public static AbstractMetricsListener onPostEventBuild(MetricsKey metricsKey, ServiceMetricsCollector<TimeCounterEvent> collector) {
|
||||
return AbstractMetricsListener.onEvent(metricsKey,
|
||||
event -> collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), metricsKey, SELF_INCREMENT_SIZE)
|
||||
public static AbstractMetricsKeyListener onPostEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector) {
|
||||
return AbstractMetricsKeyListener.onEvent(metricsKey,
|
||||
event -> MetricsSupport.increment(metricsKey, placeType, collector, event)
|
||||
);
|
||||
}
|
||||
|
||||
public static AbstractMetricsListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceType placeType, ServiceMetricsCollector<TimeCounterEvent> collector) {
|
||||
return AbstractMetricsListener.onFinish(metricsKey,
|
||||
event -> incrAndAddRt(metricsKey, placeType, collector, event)
|
||||
public static AbstractMetricsKeyListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector) {
|
||||
return AbstractMetricsKeyListener.onFinish(metricsKey,
|
||||
event -> MetricsSupport.incrAndAddRt(metricsKey, placeType, collector, event)
|
||||
);
|
||||
}
|
||||
|
||||
public static AbstractMetricsListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceType placeType, ServiceMetricsCollector<TimeCounterEvent> collector) {
|
||||
return AbstractMetricsListener.onError(metricsKey,
|
||||
event -> incrAndAddRt(metricsKey, placeType, collector, event)
|
||||
public static AbstractMetricsKeyListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector) {
|
||||
return AbstractMetricsKeyListener.onError(metricsKey,
|
||||
event -> MetricsSupport.incrAndAddRt(metricsKey, placeType, collector, event)
|
||||
);
|
||||
}
|
||||
|
||||
private static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceType placeType, ServiceMetricsCollector<TimeCounterEvent> collector, TimeCounterEvent event) {
|
||||
collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), metricsKey, SELF_INCREMENT_SIZE);
|
||||
collector.addRt(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.apache.dubbo.metrics.model;
|
||||
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
|
|
@ -38,6 +39,7 @@ import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
|
|||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
|
||||
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
|
||||
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION_METRICS_COUNTER;
|
||||
import static org.apache.dubbo.rpc.support.RpcUtils.isGenericCall;
|
||||
|
||||
/**
|
||||
|
|
@ -51,13 +53,21 @@ public class MethodMetric implements Metric {
|
|||
private String group;
|
||||
private String version;
|
||||
|
||||
public MethodMetric() {}
|
||||
private MetricSample.Type sampleType;
|
||||
|
||||
public MethodMetric() {
|
||||
}
|
||||
|
||||
public MethodMetric(String applicationName, Invocation invocation) {
|
||||
this.applicationName = applicationName;
|
||||
this.sampleType = (MetricSample.Type) invocation.get(INVOCATION_METRICS_COUNTER);
|
||||
init(invocation);
|
||||
}
|
||||
|
||||
public MetricSample.Type getSampleType() {
|
||||
return sampleType;
|
||||
}
|
||||
|
||||
public String getInterfaceName() {
|
||||
return interfaceName;
|
||||
}
|
||||
|
|
@ -106,9 +116,9 @@ public class MethodMetric implements Metric {
|
|||
String serviceUniqueName = invocation.getTargetServiceUniqueName();
|
||||
String methodName = invocation.getMethodName();
|
||||
if (invocation instanceof RpcInvocation
|
||||
&& isGenericCall(((RpcInvocation) invocation).getParameterTypesDesc(), methodName)
|
||||
&& invocation.getArguments() != null
|
||||
&& invocation.getArguments().length == 3) {
|
||||
&& isGenericCall(((RpcInvocation) invocation).getParameterTypesDesc(), methodName)
|
||||
&& invocation.getArguments() != null
|
||||
&& invocation.getArguments().length == 3) {
|
||||
methodName = ((String) invocation.getArguments()[0]).trim();
|
||||
}
|
||||
String group = null;
|
||||
|
|
@ -150,13 +160,13 @@ public class MethodMetric implements Metric {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "MethodMetric{" +
|
||||
"applicationName='" + applicationName + '\'' +
|
||||
", side='" + side + '\'' +
|
||||
", interfaceName='" + interfaceName + '\'' +
|
||||
", methodName='" + methodName + '\'' +
|
||||
", group='" + group + '\'' +
|
||||
", version='" + version + '\'' +
|
||||
'}';
|
||||
"applicationName='" + applicationName + '\'' +
|
||||
", side='" + side + '\'' +
|
||||
", interfaceName='" + interfaceName + '\'' +
|
||||
", methodName='" + methodName + '\'' +
|
||||
", group='" + group + '\'' +
|
||||
", version='" + version + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -18,19 +18,36 @@
|
|||
package org.apache.dubbo.metrics.model;
|
||||
|
||||
import org.apache.dubbo.common.Version;
|
||||
import org.apache.dubbo.metrics.collector.MethodMetricsCollector;
|
||||
import org.apache.dubbo.metrics.collector.ServiceMetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPARATOR;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_VERSION_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
|
||||
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
|
||||
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE;
|
||||
|
||||
public class MetricsSupport {
|
||||
|
||||
|
|
@ -56,4 +73,120 @@ public class MetricsSupport {
|
|||
tags.put(TAG_INTERFACE_KEY, keys[1]);
|
||||
return tags;
|
||||
}
|
||||
|
||||
public static Map<String, String> methodTags(String names) {
|
||||
String[] keys = names.split("_");
|
||||
if (keys.length != 3) {
|
||||
throw new MetricsNeverHappenException("Error names: " + names);
|
||||
}
|
||||
Map<String, String> tags = applicationTags(keys[0]);
|
||||
tags.put(TAG_INTERFACE_KEY, keys[1]);
|
||||
tags.put(TAG_METHOD_KEY, keys[2]);
|
||||
return tags;
|
||||
}
|
||||
|
||||
public static MetricsKey getMetricsKey(RpcException e) {
|
||||
MetricsKey targetKey;
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_FAILED;
|
||||
if (e.isTimeout()) {
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_TIMEOUT;
|
||||
}
|
||||
if (e.isLimitExceed()) {
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_LIMIT;
|
||||
}
|
||||
if (e.isBiz()) {
|
||||
targetKey = MetricsKey.METRIC_REQUEST_BUSINESS_FAILED;
|
||||
}
|
||||
if (e.isSerialization()) {
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_CODEC_FAILED;
|
||||
}
|
||||
if (e.isNetwork()) {
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_NETWORK_FAILED;
|
||||
}
|
||||
return targetKey;
|
||||
}
|
||||
|
||||
public static MetricsKey getAggMetricsKey(RpcException e) {
|
||||
MetricsKey targetKey;
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_FAILED_AGG;
|
||||
if (e.isTimeout()) {
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_TIMEOUT_AGG;
|
||||
}
|
||||
if (e.isLimitExceed()) {
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_LIMIT_AGG;
|
||||
}
|
||||
if (e.isBiz()) {
|
||||
targetKey = MetricsKey.METRIC_REQUEST_BUSINESS_FAILED_AGG;
|
||||
}
|
||||
if (e.isSerialization()) {
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_CODEC_FAILED_AGG;
|
||||
}
|
||||
if (e.isNetwork()) {
|
||||
targetKey = MetricsKey.METRIC_REQUESTS_NETWORK_FAILED_AGG;
|
||||
}
|
||||
return targetKey;
|
||||
}
|
||||
|
||||
public static String getSide(Invocation invocation) {
|
||||
Optional<? extends Invoker<?>> invoker = Optional.ofNullable(invocation.getInvoker());
|
||||
return invoker.isPresent() ? invoker.get().getUrl().getSide() : PROVIDER_SIDE;
|
||||
}
|
||||
|
||||
|
||||
public static String getInterfaceName(Invocation invocation) {
|
||||
String serviceUniqueName = invocation.getTargetServiceUniqueName();
|
||||
String interfaceAndVersion;
|
||||
String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
|
||||
if (arr.length == 2) {
|
||||
interfaceAndVersion = arr[1];
|
||||
} else {
|
||||
interfaceAndVersion = arr[0];
|
||||
}
|
||||
String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
|
||||
return ivArr[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Incr service num
|
||||
*/
|
||||
public static void increment(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
|
||||
collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dec service num
|
||||
*/
|
||||
public static void dec(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
|
||||
collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Incr service num&&rt
|
||||
*/
|
||||
public static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector, TimeCounterEvent event) {
|
||||
collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
collector.addRt(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Incr method num
|
||||
*/
|
||||
public static void increment(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
|
||||
collector.increment(event.appName(), event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dec method num
|
||||
*/
|
||||
public static void dec(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
|
||||
collector.increment(event.appName(), event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Incr method num&&rt
|
||||
*/
|
||||
public static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, TimeCounterEvent event) {
|
||||
collector.increment(event.appName(), event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
collector.addRt(event.appName(), event.getAttachmentValue(INVOCATION), placeType.getType(), event.getTimePair().calc());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,20 @@ package org.apache.dubbo.metrics.model.key;
|
|||
|
||||
import io.micrometer.common.lang.Nullable;
|
||||
|
||||
/**
|
||||
* The overall event set, including the event processing functions in three stages
|
||||
*/
|
||||
public class CategoryOverall {
|
||||
|
||||
private final MetricsCat post;
|
||||
private MetricsCat finish;
|
||||
private MetricsCat error;
|
||||
|
||||
public CategoryOverall(MetricsPlaceType placeType, MetricsCat post, @Nullable MetricsCat finish, @Nullable MetricsCat error) {
|
||||
/**
|
||||
* @param placeType When placeType is null, it means that placeType is obtained dynamically
|
||||
* @param post Statistics of the number of events, as long as it occurs, it will take effect, so it cannot be null
|
||||
*/
|
||||
public CategoryOverall(@Nullable MetricsPlaceValue placeType, MetricsCat post, @Nullable MetricsCat finish, @Nullable MetricsCat error) {
|
||||
this.post = post.setPlaceType(placeType);
|
||||
if (finish != null) {
|
||||
this.finish = finish.setPlaceType(placeType);
|
||||
|
|
|
|||
|
|
@ -18,31 +18,34 @@
|
|||
package org.apache.dubbo.metrics.model.key;
|
||||
|
||||
import org.apache.dubbo.metrics.collector.CombMetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsListener;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class MetricsCat {
|
||||
|
||||
private MetricsPlaceType placeType;
|
||||
private final Function<CombMetricsCollector<TimeCounterEvent>, AbstractMetricsListener> eventFunc;
|
||||
private MetricsPlaceValue placeType;
|
||||
private final Function<CombMetricsCollector, AbstractMetricsKeyListener> eventFunc;
|
||||
|
||||
public MetricsCat(MetricsKey metricsKey, BiFunction<MetricsKey, CombMetricsCollector<TimeCounterEvent>, AbstractMetricsListener> biFunc) {
|
||||
public MetricsCat(MetricsKey metricsKey, BiFunction<MetricsKey, CombMetricsCollector, AbstractMetricsKeyListener> biFunc) {
|
||||
this.eventFunc = collector -> biFunc.apply(metricsKey, collector);
|
||||
}
|
||||
|
||||
public MetricsCat(MetricsKey metricsKey, TpFunction<MetricsKey, MetricsPlaceType, CombMetricsCollector<TimeCounterEvent>, AbstractMetricsListener> tpFunc) {
|
||||
/**
|
||||
* @param metricsKey The key that the current category listens to,not necessarily the export key(export key may be dynamic)
|
||||
* @param tpFunc Build the func that outputs the MetricsListener by listen metricsKey
|
||||
*/
|
||||
public MetricsCat(MetricsKey metricsKey, TpFunction<MetricsKey, MetricsPlaceValue, CombMetricsCollector, AbstractMetricsKeyListener> tpFunc) {
|
||||
this.eventFunc = collector -> tpFunc.apply(metricsKey, placeType, collector);
|
||||
}
|
||||
|
||||
public MetricsCat setPlaceType(MetricsPlaceType placeType) {
|
||||
public MetricsCat setPlaceType(MetricsPlaceValue placeType) {
|
||||
this.placeType = placeType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Function<CombMetricsCollector<TimeCounterEvent>, AbstractMetricsListener> getEventFunc() {
|
||||
public Function<CombMetricsCollector, AbstractMetricsKeyListener> getEventFunc() {
|
||||
return eventFunc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,12 @@ public enum MetricsKey {
|
|||
METRIC_REQUESTS_TOTAL_AGG("dubbo.%s.requests.total.aggregate", "Aggregated Total Requests"),
|
||||
METRIC_REQUESTS_SUCCEED_AGG("dubbo.%s.requests.succeed.aggregate", "Aggregated Succeed Requests"),
|
||||
METRIC_REQUESTS_FAILED_AGG("dubbo.%s.requests.failed.aggregate", "Aggregated Failed Requests"),
|
||||
METRIC_REQUESTS_BUSINESS_FAILED_AGG("dubbo.%s.requests.business.failed.aggregate", "Aggregated Business Failed Requests"),
|
||||
METRIC_REQUEST_BUSINESS_FAILED_AGG("dubbo.%s.requests.business.failed.aggregate", "Aggregated Business Failed Requests"),
|
||||
METRIC_REQUESTS_TIMEOUT_AGG("dubbo.%s.requests.timeout.failed.aggregate", "Aggregated timeout Failed Requests"),
|
||||
METRIC_REQUESTS_LIMIT_AGG("dubbo.%s.requests.limit.aggregate", "Aggregated limit Requests"),
|
||||
METRIC_REQUESTS_TOTAL_FAILED_AGG("dubbo.%s.requests.failed.total.aggregate", "Aggregated failed total Requests"),
|
||||
METRIC_REQUESTS_TOTAL_NETWORK_FAILED_AGG("dubbo.%s.requests.failed.network.total.aggregate", "Aggregated failed network total Requests"),
|
||||
METRIC_REQUESTS_TOTAL_CODEC_FAILED_AGG("dubbo.%s.requests.failed.codec.total.aggregate", "Aggregated failed codec total Requests"),
|
||||
METRIC_REQUESTS_NETWORK_FAILED_AGG("dubbo.%s.requests.failed.network.total.aggregate", "Aggregated failed network total Requests"),
|
||||
METRIC_REQUESTS_CODEC_FAILED_AGG("dubbo.%s.requests.failed.codec.total.aggregate", "Aggregated failed codec total Requests"),
|
||||
METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG("dubbo.%s.requests.failed.service.unavailable.total.aggregate", "Aggregated failed codec total Requests"),
|
||||
|
||||
METRIC_QPS("dubbo.%s.qps.total", "Query Per Seconds"),
|
||||
|
|
|
|||
|
|
@ -17,9 +17,11 @@
|
|||
|
||||
package org.apache.dubbo.metrics.model.key;
|
||||
|
||||
import io.micrometer.common.lang.Nullable;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Let {@link MetricsKey MetricsKey} output dynamic, custom string content
|
||||
|
|
@ -31,15 +33,21 @@ public class MetricsKeyWrapper {
|
|||
*/
|
||||
private final MetricsKey metricsKey;
|
||||
|
||||
/**
|
||||
* The value corresponding to the MetricsKey placeholder (if exist)
|
||||
*/
|
||||
private final MetricsPlaceValue placeType;
|
||||
|
||||
private final MetricsPlaceType placeType;
|
||||
|
||||
public MetricsKeyWrapper(MetricsKey metricsKey, MetricsPlaceType placeType) {
|
||||
/**
|
||||
* When the MetricsPlaceType is null, it is equivalent to a single MetricsKey.
|
||||
* Use the decorator mode to share a container with MetricsKey
|
||||
*/
|
||||
public MetricsKeyWrapper(MetricsKey metricsKey, @Nullable MetricsPlaceValue placeType) {
|
||||
this.metricsKey = metricsKey;
|
||||
this.placeType = placeType;
|
||||
}
|
||||
|
||||
public MetricsPlaceType getPlaceType() {
|
||||
public MetricsPlaceValue getPlaceType() {
|
||||
return placeType;
|
||||
}
|
||||
|
||||
|
|
@ -55,11 +63,14 @@ public class MetricsKeyWrapper {
|
|||
return metricsKey == getMetricsKey() && registryOpType.equals(getType());
|
||||
}
|
||||
|
||||
public boolean isServiceLevel() {
|
||||
return getPlaceType().getMetricsLevel().equals(MetricsLevel.SERVICE);
|
||||
public MetricsLevel getLevel() {
|
||||
return getPlaceType().getMetricsLevel();
|
||||
}
|
||||
|
||||
public String targetKey() {
|
||||
if (placeType == null) {
|
||||
return metricsKey.getName();
|
||||
}
|
||||
try {
|
||||
return String.format(metricsKey.getName(), getType());
|
||||
} catch (Exception ignore) {
|
||||
|
|
@ -68,6 +79,9 @@ public class MetricsKeyWrapper {
|
|||
}
|
||||
|
||||
public String targetDesc() {
|
||||
if (placeType == null) {
|
||||
return metricsKey.getDescription();
|
||||
}
|
||||
try {
|
||||
return String.format(metricsKey.getDescription(), getType());
|
||||
} catch (Exception ignore) {
|
||||
|
|
@ -76,6 +90,37 @@ public class MetricsKeyWrapper {
|
|||
}
|
||||
|
||||
public Map<String, String> tagName(String key) {
|
||||
return isServiceLevel() ? MetricsSupport.serviceTags(key) : MetricsSupport.applicationTags(key);
|
||||
MetricsLevel level = getLevel();
|
||||
switch (level) {
|
||||
case APP:
|
||||
return MetricsSupport.applicationTags(key);
|
||||
case SERVICE:
|
||||
return MetricsSupport.serviceTags(key);
|
||||
case METHOD:
|
||||
return MetricsSupport.methodTags(key);
|
||||
}
|
||||
return MetricsSupport.applicationTags(key);
|
||||
}
|
||||
|
||||
public static MetricsKeyWrapper wrapper(MetricsKey metricsKey) {
|
||||
return new MetricsKeyWrapper(metricsKey, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
MetricsKeyWrapper wrapper = (MetricsKeyWrapper) o;
|
||||
|
||||
if (metricsKey != wrapper.metricsKey) return false;
|
||||
return Objects.equals(placeType, wrapper.placeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = metricsKey != null ? metricsKey.hashCode() : 0;
|
||||
result = 31 * result + (placeType != null ? placeType.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@
|
|||
package org.apache.dubbo.metrics.model.key;
|
||||
|
||||
public enum MetricsLevel {
|
||||
APP,SERVICE,CONFIG
|
||||
APP, SERVICE, METHOD, CONFIG
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,18 +17,21 @@
|
|||
|
||||
package org.apache.dubbo.metrics.model.key;
|
||||
|
||||
public class MetricsPlaceType {
|
||||
/**
|
||||
* The value corresponding to the placeholder in {@link MetricsKey}
|
||||
*/
|
||||
public class MetricsPlaceValue {
|
||||
|
||||
private final String type;
|
||||
private final MetricsLevel metricsLevel;
|
||||
|
||||
private MetricsPlaceType(String type, MetricsLevel metricsLevel) {
|
||||
private MetricsPlaceValue(String type, MetricsLevel metricsLevel) {
|
||||
this.type = type;
|
||||
this.metricsLevel = metricsLevel;
|
||||
}
|
||||
|
||||
public static MetricsPlaceType of(String type, MetricsLevel metricsLevel) {
|
||||
return new MetricsPlaceType(type, metricsLevel);
|
||||
public static MetricsPlaceValue of(String type, MetricsLevel metricsLevel) {
|
||||
return new MetricsPlaceValue(type, metricsLevel);
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
|
|
@ -38,4 +41,22 @@ public class MetricsPlaceType {
|
|||
public MetricsLevel getMetricsLevel() {
|
||||
return metricsLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
MetricsPlaceValue that = (MetricsPlaceValue) o;
|
||||
|
||||
if (!type.equals(that.type)) return false;
|
||||
return metricsLevel == that.metricsLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = type.hashCode();
|
||||
result = 31 * result + metricsLevel.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -44,4 +44,5 @@ public class TypeWrapper {
|
|||
Assert.notNull(type, "Type can not be null");
|
||||
return type.equals(postType) || type.equals(finishType) || type.equals(errorType);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,23 +17,22 @@
|
|||
package org.apache.dubbo.metrics.model.sample;
|
||||
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CounterMetricSample<T extends Number> extends MetricSample {
|
||||
public class CounterMetricSample<T extends Number> extends MetricSample {
|
||||
|
||||
private final T value;
|
||||
|
||||
public CounterMetricSample(String name, String description, Map<String, String> tags,
|
||||
MetricsCategory category, T value ) {
|
||||
MetricsCategory category, T value) {
|
||||
super(name, description, tags, Type.COUNTER, category);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public CounterMetricSample(String name, String description, Map<String, String> tags, MetricsCategory category,
|
||||
String baseUnit, T value) {
|
||||
super(name, description, tags, Type.COUNTER, category, baseUnit);
|
||||
this.value = value;
|
||||
public CounterMetricSample(MetricsKeyWrapper metricsKeyWrapper, Map<String, String> tags, MetricsCategory category, T value) {
|
||||
this(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), tags, category, value);
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.metrics.model.sample;
|
|||
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
|
@ -37,6 +38,10 @@ public class GaugeMetricSample<T> extends MetricSample {
|
|||
this(metricsKey.getName(), metricsKey.getDescription(), tags, category, null, value, apply);
|
||||
}
|
||||
|
||||
public GaugeMetricSample(MetricsKeyWrapper metricsKeyWrapper, Map<String, String> tags, MetricsCategory category, T value, ToDoubleFunction<T> apply) {
|
||||
this(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), tags, category, null, value, apply);
|
||||
}
|
||||
|
||||
public GaugeMetricSample(String name, String description, Map<String, String> tags, MetricsCategory category, T value, ToDoubleFunction<T> apply) {
|
||||
this(name, description, tags, category, null, value, apply);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
package org.apache.dubbo.metrics.report;
|
||||
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -31,6 +31,6 @@ public interface MetricsExport {
|
|||
/**
|
||||
* export all.
|
||||
*/
|
||||
List<GaugeMetricSample> export(MetricsCategory category);
|
||||
List<MetricSample> export(MetricsCategory category);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ package org.apache.dubbo.metrics.event;
|
|||
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.config.context.ConfigManager;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsListener;
|
||||
import org.apache.dubbo.metrics.listener.MetricsLifeListener;
|
||||
import org.apache.dubbo.metrics.listener.MetricsListener;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
@ -39,7 +39,7 @@ public class SimpleMetricsEventMulticasterTest {
|
|||
public void setup() {
|
||||
eventMulticaster = new SimpleMetricsEventMulticaster();
|
||||
objects = new Object[]{obj};
|
||||
eventMulticaster.addListener(new MetricsListener<MetricsEvent>() {
|
||||
eventMulticaster.addListener(new AbstractMetricsListener<MetricsEvent>() {
|
||||
@Override
|
||||
public void onEvent(MetricsEvent event) {
|
||||
objects[0] = new Object();
|
||||
|
|
@ -52,7 +52,7 @@ public class SimpleMetricsEventMulticasterTest {
|
|||
ConfigManager configManager = new ConfigManager(applicationModel);
|
||||
configManager.setApplication(applicationConfig);
|
||||
applicationModel.setConfigManager(configManager);
|
||||
requestEvent = new TimeCounterEvent(applicationModel) {
|
||||
requestEvent = new TimeCounterEvent(applicationModel,null) {
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +77,11 @@ public class SimpleMetricsEventMulticasterTest {
|
|||
//do onEventFinish with MetricsLifeListener
|
||||
eventMulticaster.addListener((new MetricsLifeListener<TimeCounterEvent>() {
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof TimeCounterEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(TimeCounterEvent event) {
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ import org.apache.dubbo.config.context.ConfigManager;
|
|||
import org.apache.dubbo.metrics.collector.CombMetricsCollector;
|
||||
import org.apache.dubbo.metrics.collector.MetricsCollector;
|
||||
import org.apache.dubbo.metrics.config.event.ConfigCenterEvent;
|
||||
import org.apache.dubbo.metrics.config.event.ConfigCenterMetricsDispatcher;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.config.event.ConfigCenterSubDispatcher;
|
||||
import org.apache.dubbo.metrics.model.ConfigCenterMetric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
|
|
@ -45,7 +43,7 @@ import static org.apache.dubbo.metrics.model.MetricsCategory.CONFIGCENTER;
|
|||
* Config center implementation of {@link MetricsCollector}
|
||||
*/
|
||||
@Activate
|
||||
public class ConfigCenterMetricsCollector extends CombMetricsCollector<TimeCounterEvent> {
|
||||
public class ConfigCenterMetricsCollector extends CombMetricsCollector<ConfigCenterEvent> {
|
||||
|
||||
private Boolean collectEnabled = null;
|
||||
private final ApplicationModel applicationModel;
|
||||
|
|
@ -55,7 +53,7 @@ public class ConfigCenterMetricsCollector extends CombMetricsCollector<TimeCount
|
|||
public ConfigCenterMetricsCollector(ApplicationModel applicationModel) {
|
||||
super(null);
|
||||
this.applicationModel = applicationModel;
|
||||
super.setEventMulticaster(new ConfigCenterMetricsDispatcher(this));
|
||||
super.setEventMulticaster(new ConfigCenterSubDispatcher(this));
|
||||
}
|
||||
|
||||
public void setCollectEnabled(Boolean collectEnabled) {
|
||||
|
|
@ -94,9 +92,4 @@ public class ConfigCenterMetricsCollector extends CombMetricsCollector<TimeCount
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof ConfigCenterEvent;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,7 @@ public class ConfigCenterEvent extends TimeCounterEvent {
|
|||
|
||||
|
||||
public ConfigCenterEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
|
||||
super(applicationModel);
|
||||
super.typeWrapper = typeWrapper;
|
||||
super(applicationModel,typeWrapper);
|
||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||
ConfigCenterMetricsCollector collector;
|
||||
if (!beanFactory.isDestroyed()) {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import org.apache.dubbo.metrics.config.collector.ConfigCenterMetricsCollector;
|
|||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsListener;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SIZE;
|
||||
|
|
@ -30,11 +30,11 @@ import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTAC
|
|||
import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTACHMENT_KEY_CONFIG_PROTOCOL;
|
||||
|
||||
|
||||
public final class ConfigCenterMetricsDispatcher extends SimpleMetricsEventMulticaster {
|
||||
public final class ConfigCenterSubDispatcher extends SimpleMetricsEventMulticaster {
|
||||
|
||||
public ConfigCenterMetricsDispatcher(ConfigCenterMetricsCollector collector) {
|
||||
public ConfigCenterSubDispatcher(ConfigCenterMetricsCollector collector) {
|
||||
|
||||
super.addListener(new AbstractMetricsListener(MetricsKey.CONFIGCENTER_METRIC_TOTAL) {
|
||||
super.addListener(new AbstractMetricsKeyListener(MetricsKey.CONFIGCENTER_METRIC_TOTAL) {
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof ConfigCenterEvent;
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_CODEC_FAILED;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_FAILED;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_LIMIT;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_NETWORK_FAILED;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_PROCESSING;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SUCCEED;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_TIMEOUT;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_TOTAL_FAILED;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUEST_BUSINESS_FAILED;
|
||||
|
||||
public interface DefaultConstants {
|
||||
|
||||
String METRIC_FILTER_EVENT = "metric_filter_event";
|
||||
|
||||
String METRIC_THROWABLE = "metric_filter_throwable";
|
||||
|
||||
List<MetricsKeyWrapper> METHOD_LEVEL_KEYS = Arrays.asList(
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_PROCESSING, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_PROCESSING, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_SUCCEED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_SUCCEED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUEST_BUSINESS_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUEST_BUSINESS_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_TIMEOUT, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_TIMEOUT, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_LIMIT, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_LIMIT, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_TOTAL_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_TOTAL_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_NETWORK_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_NETWORK_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_CODEC_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_CODEC_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD))
|
||||
);
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
package org.apache.dubbo.metrics;
|
||||
|
||||
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||
|
|
@ -35,7 +34,6 @@ public class MetricsScopeModelInitializer implements ScopeModelInitializer {
|
|||
@Override
|
||||
public void initializeApplicationModel(ApplicationModel applicationModel) {
|
||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||
beanFactory.registerBean(DefaultMetricsCollector.class);
|
||||
beanFactory.registerBean(MetricsDispatcher.class);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,26 +21,32 @@ import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
|||
import org.apache.dubbo.config.MetricsConfig;
|
||||
import org.apache.dubbo.config.context.ConfigManager;
|
||||
import org.apache.dubbo.config.nested.AggregationConfig;
|
||||
import org.apache.dubbo.metrics.MetricsConstants;
|
||||
import org.apache.dubbo.metrics.aggregate.TimeWindowCounter;
|
||||
import org.apache.dubbo.metrics.aggregate.TimeWindowQuantile;
|
||||
import org.apache.dubbo.metrics.event.MethodEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.RTEvent;
|
||||
import org.apache.dubbo.metrics.listener.MetricsListener;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE;
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.QPS;
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.REQUESTS;
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.RT;
|
||||
|
|
@ -49,68 +55,101 @@ import static org.apache.dubbo.metrics.model.MetricsCategory.RT;
|
|||
* Aggregation metrics collector implementation of {@link MetricsCollector}.
|
||||
* This collector only enabled when metrics aggregation config is enabled.
|
||||
*/
|
||||
public class AggregateMetricsCollector implements MetricsCollector, MetricsListener {
|
||||
public class AggregateMetricsCollector implements MetricsCollector<RequestEvent> {
|
||||
private int bucketNum;
|
||||
private int timeWindowSeconds;
|
||||
private final Map<String, ConcurrentHashMap<MethodMetric, TimeWindowCounter>> methodTypeCounter = new ConcurrentHashMap<>();
|
||||
private final Map<MetricsKeyWrapper, ConcurrentHashMap<MethodMetric, TimeWindowCounter>> methodTypeCounter = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<MethodMetric, TimeWindowQuantile> rt = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<MethodMetric, TimeWindowCounter> qps = new ConcurrentHashMap<>();
|
||||
private final ApplicationModel applicationModel;
|
||||
private static final Integer DEFAULT_COMPRESSION = 100;
|
||||
private static final Integer DEFAULT_BUCKET_NUM = 10;
|
||||
private static final Integer DEFAULT_TIME_WINDOW_SECONDS = 120;
|
||||
private Boolean collectEnabled = null;
|
||||
|
||||
public AggregateMetricsCollector(ApplicationModel applicationModel) {
|
||||
this.registryEventTypeHandler();
|
||||
|
||||
this.applicationModel = applicationModel;
|
||||
ConfigManager configManager = applicationModel.getApplicationConfigManager();
|
||||
MetricsConfig config = configManager.getMetrics().orElse(null);
|
||||
if (config != null && config.getAggregation() != null && (Boolean.TRUE.equals(config.getAggregation().getEnabled()))) {
|
||||
if (isCollectEnabled()) {
|
||||
// only registered when aggregation is enabled.
|
||||
registerListener();
|
||||
|
||||
AggregationConfig aggregation = config.getAggregation();
|
||||
this.bucketNum = aggregation.getBucketNum() == null ? DEFAULT_BUCKET_NUM : aggregation.getBucketNum();
|
||||
this.timeWindowSeconds = aggregation.getTimeWindowSeconds() == null ? DEFAULT_TIME_WINDOW_SECONDS : aggregation.getTimeWindowSeconds();
|
||||
Optional<MetricsConfig> optional = configManager.getMetrics();
|
||||
if (optional.isPresent()) {
|
||||
registerListener();
|
||||
AggregationConfig aggregation = optional.get().getAggregation();
|
||||
this.bucketNum = aggregation.getBucketNum() == null ? DEFAULT_BUCKET_NUM : aggregation.getBucketNum();
|
||||
this.timeWindowSeconds = aggregation.getTimeWindowSeconds() == null ? DEFAULT_TIME_WINDOW_SECONDS : aggregation.getTimeWindowSeconds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setCollectEnabled(Boolean collectEnabled) {
|
||||
if (collectEnabled != null) {
|
||||
this.collectEnabled = collectEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isCollectEnabled() {
|
||||
if (collectEnabled == null) {
|
||||
ConfigManager configManager = applicationModel.getApplicationConfigManager();
|
||||
configManager.getMetrics().ifPresent(metricsConfig -> setCollectEnabled(metricsConfig.getAggregation().getEnabled()));
|
||||
}
|
||||
return Optional.ofNullable(collectEnabled).orElse(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(MetricsEvent event) {
|
||||
if (event instanceof RTEvent) {
|
||||
onRTEvent((RTEvent) event);
|
||||
} else if (event instanceof MethodEvent) {
|
||||
onRequestEvent((MethodEvent) event);
|
||||
}
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RequestEvent;
|
||||
}
|
||||
|
||||
private void onRTEvent(RTEvent event) {
|
||||
MethodMetric metric = (MethodMetric) event.getMetric();
|
||||
Long responseTime = event.getRt();
|
||||
@Override
|
||||
public void onEvent(RequestEvent event) {
|
||||
MethodMetric metric = calcWindowCounter(event, MetricsKey.METRIC_REQUESTS);
|
||||
TimeWindowCounter qpsCounter = ConcurrentHashMapUtils.computeIfAbsent(qps, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds));
|
||||
qpsCounter.increment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventFinish(RequestEvent event) {
|
||||
MetricsKey targetKey = MetricsKey.METRIC_REQUESTS_SUCCEED;
|
||||
Object throwableObj = event.getAttachmentValue(METRIC_THROWABLE);
|
||||
if (throwableObj != null) {
|
||||
targetKey = MetricsSupport.getAggMetricsKey((RpcException) throwableObj);
|
||||
}
|
||||
calcWindowCounter(event, targetKey);
|
||||
onRTEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventError(RequestEvent event) {
|
||||
MetricsKey targetKey = MetricsKey.METRIC_REQUESTS_FAILED;
|
||||
Object throwableObj = event.getAttachmentValue(METRIC_THROWABLE);
|
||||
if (throwableObj != null) {
|
||||
targetKey = MetricsSupport.getAggMetricsKey((RpcException) throwableObj);
|
||||
}
|
||||
calcWindowCounter(event, targetKey);
|
||||
onRTEvent(event);
|
||||
}
|
||||
|
||||
private void onRTEvent(RequestEvent event) {
|
||||
MethodMetric metric = new MethodMetric(applicationModel.getApplicationName(), event.getAttachmentValue(MetricsConstants.INVOCATION));
|
||||
long responseTime = event.getTimePair().calc();
|
||||
TimeWindowQuantile quantile = ConcurrentHashMapUtils.computeIfAbsent(rt, metric, k -> new TimeWindowQuantile(DEFAULT_COMPRESSION, bucketNum, timeWindowSeconds));
|
||||
quantile.add(responseTime);
|
||||
}
|
||||
|
||||
|
||||
private void onRequestEvent(MethodEvent event) {
|
||||
MethodMetric metric = event.getMethodMetric();
|
||||
private MethodMetric calcWindowCounter(RequestEvent event, MetricsKey targetKey) {
|
||||
MetricsPlaceValue placeType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.SERVICE);
|
||||
MetricsKeyWrapper metricsKeyWrapper = new MetricsKeyWrapper(targetKey, placeType);
|
||||
MethodMetric metric = new MethodMetric(applicationModel.getApplicationName(), event.getAttachmentValue(MetricsConstants.INVOCATION));
|
||||
|
||||
String type = event.getType();
|
||||
ConcurrentMap<MethodMetric, TimeWindowCounter> counter = methodTypeCounter.computeIfAbsent(metricsKeyWrapper, k -> new ConcurrentHashMap<>());
|
||||
|
||||
ConcurrentMap<MethodMetric, TimeWindowCounter> counter = methodTypeCounter.get(type);
|
||||
|
||||
if (counter == null) {
|
||||
return;
|
||||
}
|
||||
TimeWindowCounter windowCounter = ConcurrentHashMapUtils.computeIfAbsent(counter, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds));
|
||||
|
||||
if (MetricsEvent.Type.TOTAL.getNameByType(PROVIDER_SIDE).equals(type)
|
||||
|| MetricsEvent.Type.TOTAL.getNameByType(CONSUMER_SIDE).equals(type)) {
|
||||
TimeWindowCounter qpsCounter = ConcurrentHashMapUtils.computeIfAbsent(qps, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds));
|
||||
qpsCounter.increment();
|
||||
}
|
||||
windowCounter.increment();
|
||||
return metric;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -129,21 +168,21 @@ public class AggregateMetricsCollector implements MetricsCollector, MetricsListe
|
|||
}
|
||||
|
||||
private void collectBySide(List<MetricSample> list, String side) {
|
||||
collectMethod(list, MetricsEvent.Type.TOTAL.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.SUCCEED.getNameByType(side), MetricsKey.METRIC_REQUESTS_SUCCEED_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side), MetricsKey.METRIC_REQUESTS_FAILED_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.BUSINESS_FAILED.getNameByType(side), MetricsKey.METRIC_REQUESTS_BUSINESS_FAILED_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.REQUEST_TIMEOUT.getNameByType(side), MetricsKey.METRIC_REQUESTS_TIMEOUT_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.REQUEST_LIMIT.getNameByType(side), MetricsKey.METRIC_REQUESTS_LIMIT_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.TOTAL_FAILED.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_FAILED_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.NETWORK_EXCEPTION.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_NETWORK_FAILED_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.CODEC_EXCEPTION.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_CODEC_FAILED_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG);
|
||||
collectMethod(list, MetricsEvent.Type.NO_INVOKER_AVAILABLE.getNameByType(side), MetricsKey.INVOKER_NO_AVAILABLE_COUNT);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUESTS_TOTAL_AGG);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUESTS_SUCCEED_AGG);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUESTS_FAILED_AGG);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUEST_BUSINESS_FAILED_AGG);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUESTS_TIMEOUT_AGG);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUESTS_LIMIT_AGG);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUESTS_TOTAL_FAILED_AGG);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUESTS_NETWORK_FAILED_AGG);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUESTS_CODEC_FAILED_AGG);
|
||||
collectMethod(list, side, MetricsKey.METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG);
|
||||
}
|
||||
|
||||
private void collectMethod(List<MetricSample> list, String eventType, MetricsKey metricsKey) {
|
||||
ConcurrentHashMap<MethodMetric, TimeWindowCounter> windowCounter = methodTypeCounter.get(eventType);
|
||||
private void collectMethod(List<MetricSample> list, String side, MetricsKey metricsKey) {
|
||||
MetricsKeyWrapper metricsKeyWrapper = new MetricsKeyWrapper(metricsKey, MetricsPlaceValue.of(side, MetricsLevel.SERVICE));
|
||||
ConcurrentHashMap<MethodMetric, TimeWindowCounter> windowCounter = methodTypeCounter.get(metricsKeyWrapper);
|
||||
if (windowCounter != null) {
|
||||
windowCounter.forEach((k, v) -> list.add(new GaugeMetricSample<>(metricsKey.getNameByType(k.getSide()),
|
||||
metricsKey.getDescription(), k.getTags(), REQUESTS, v, TimeWindowCounter::get)));
|
||||
|
|
@ -164,27 +203,8 @@ public class AggregateMetricsCollector implements MetricsCollector, MetricsListe
|
|||
});
|
||||
}
|
||||
|
||||
private void registryEventTypeHandler() {
|
||||
registryBySide(PROVIDER_SIDE);
|
||||
registryBySide(CONSUMER_SIDE);
|
||||
}
|
||||
|
||||
private void registryBySide(String side) {
|
||||
methodTypeCounter.put(MetricsEvent.Type.TOTAL.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.SUCCEED.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.BUSINESS_FAILED.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.REQUEST_TIMEOUT.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.REQUEST_LIMIT.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.TOTAL_FAILED.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.NETWORK_EXCEPTION.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.CODEC_EXCEPTION.getNameByType(side), new ConcurrentHashMap<>());
|
||||
methodTypeCounter.put(MetricsEvent.Type.NO_INVOKER_AVAILABLE.getNameByType(side), new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
private void registerListener() {
|
||||
applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).addListener(this);
|
||||
applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).getEventMulticaster().addListener(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,48 +16,71 @@
|
|||
*/
|
||||
|
||||
package org.apache.dubbo.metrics.collector;
|
||||
import org.apache.dubbo.metrics.collector.sample.MethodMetricsSampler;
|
||||
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.metrics.DefaultConstants;
|
||||
import org.apache.dubbo.metrics.collector.sample.MetricsCountSampleConfigurer;
|
||||
import org.apache.dubbo.metrics.collector.sample.MetricsSampler;
|
||||
import org.apache.dubbo.metrics.collector.sample.SimpleMetricsCountSampler;
|
||||
import org.apache.dubbo.metrics.collector.sample.ThreadPoolMetricsSampler;
|
||||
import org.apache.dubbo.metrics.data.BaseStatComposite;
|
||||
import org.apache.dubbo.metrics.data.MethodStatComposite;
|
||||
import org.apache.dubbo.metrics.data.RtStatComposite;
|
||||
import org.apache.dubbo.metrics.event.DefaultSubDispatcher;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.listener.MetricsListener;
|
||||
import org.apache.dubbo.metrics.event.RequestBeforeEvent;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.metrics.model.ApplicationMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.APPLICATION;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.APPLICATION_METRIC_INFO;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link MetricsCollector}
|
||||
*/
|
||||
public class DefaultMetricsCollector implements MetricsCollector {
|
||||
@Activate
|
||||
public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent> {
|
||||
|
||||
private boolean collectEnabled = false;
|
||||
|
||||
private volatile boolean threadpoolCollectEnabled=false;
|
||||
private final SimpleMetricsEventMulticaster eventMulticaster;
|
||||
private final MethodMetricsSampler methodSampler = new MethodMetricsSampler(this);
|
||||
private volatile boolean threadpoolCollectEnabled = false;
|
||||
private final ThreadPoolMetricsSampler threadPoolSampler = new ThreadPoolMetricsSampler(this);
|
||||
private String applicationName;
|
||||
private ApplicationModel applicationModel;
|
||||
private final List<MetricsSampler> samplers = new ArrayList<>();
|
||||
|
||||
public DefaultMetricsCollector() {
|
||||
this.eventMulticaster = new SimpleMetricsEventMulticaster();
|
||||
samplers.add(methodSampler);
|
||||
super(new BaseStatComposite() {
|
||||
@Override
|
||||
protected void init(MethodStatComposite methodStatComposite) {
|
||||
methodStatComposite.initWrapper(DefaultConstants.METHOD_LEVEL_KEYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(RtStatComposite rtStatComposite) {
|
||||
rtStatComposite.init(MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD),
|
||||
MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD));
|
||||
}
|
||||
});
|
||||
super.setEventMulticaster(new DefaultSubDispatcher(this));
|
||||
samplers.add(applicationSampler);
|
||||
samplers.add(threadPoolSampler);
|
||||
}
|
||||
|
||||
public void addSampler(MetricsSampler sampler){
|
||||
public void addSampler(MetricsSampler sampler) {
|
||||
samplers.add(sampler);
|
||||
}
|
||||
|
||||
public void setApplicationName(String applicationName) {
|
||||
this.applicationName = applicationName;
|
||||
}
|
||||
|
|
@ -70,10 +93,6 @@ public class DefaultMetricsCollector implements MetricsCollector {
|
|||
return this.applicationModel;
|
||||
}
|
||||
|
||||
public SimpleMetricsEventMulticaster getEventMulticaster() {
|
||||
return this.eventMulticaster;
|
||||
}
|
||||
|
||||
public void setCollectEnabled(Boolean collectEnabled) {
|
||||
this.collectEnabled = collectEnabled;
|
||||
}
|
||||
|
|
@ -90,14 +109,6 @@ public class DefaultMetricsCollector implements MetricsCollector {
|
|||
this.threadpoolCollectEnabled = threadpoolCollectEnabled;
|
||||
}
|
||||
|
||||
public MethodMetricsSampler getMethodSampler() {
|
||||
return this.methodSampler;
|
||||
}
|
||||
|
||||
public ThreadPoolMetricsSampler getThreadPoolSampler() {
|
||||
return this.threadPoolSampler;
|
||||
}
|
||||
|
||||
public void collectApplication(ApplicationModel applicationModel) {
|
||||
this.setApplicationName(applicationModel.getApplicationName());
|
||||
this.applicationModel = applicationModel;
|
||||
|
|
@ -111,15 +122,21 @@ public class DefaultMetricsCollector implements MetricsCollector {
|
|||
@Override
|
||||
public List<MetricSample> collect() {
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
if (!isCollectEnabled()) {
|
||||
return list;
|
||||
}
|
||||
|
||||
for (MetricsSampler sampler : samplers) {
|
||||
List<MetricSample> sample = sampler.sample();
|
||||
list.addAll(sample);
|
||||
}
|
||||
list.addAll(super.export(MetricsCategory.REQUESTS));
|
||||
return list;
|
||||
}
|
||||
|
||||
public void addListener(MetricsListener listener) {
|
||||
this.eventMulticaster.addListener(listener);
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RequestEvent || event instanceof RequestBeforeEvent;
|
||||
}
|
||||
|
||||
public SimpleMetricsCountSampler<String, MetricsEvent.Type, ApplicationMetric> applicationSampler = new SimpleMetricsCountSampler<String, MetricsEvent.Type, ApplicationMetric>() {
|
||||
|
|
@ -127,17 +144,17 @@ public class DefaultMetricsCollector implements MetricsCollector {
|
|||
public List<MetricSample> sample() {
|
||||
List<MetricSample> samples = new ArrayList<>();
|
||||
this.getCount(MetricsEvent.Type.APPLICATION_INFO).filter(e -> !e.isEmpty())
|
||||
.ifPresent(map -> map.forEach((k, v) ->
|
||||
samples.add(new CounterMetricSample<>(APPLICATION_METRIC_INFO.getName(),
|
||||
APPLICATION_METRIC_INFO.getDescription(),
|
||||
k.getTags(), APPLICATION, v)))
|
||||
);
|
||||
.ifPresent(map -> map.forEach((k, v) ->
|
||||
samples.add(new CounterMetricSample<>(APPLICATION_METRIC_INFO.getName(),
|
||||
APPLICATION_METRIC_INFO.getDescription(),
|
||||
k.getTags(), APPLICATION, v)))
|
||||
);
|
||||
return samples;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void countConfigure(
|
||||
MetricsCountSampleConfigurer<String, MetricsEvent.Type, ApplicationMetric> sampleConfigure) {
|
||||
MetricsCountSampleConfigurer<String, MetricsEvent.Type, ApplicationMetric> sampleConfigure) {
|
||||
sampleConfigure.configureMetrics(configure -> new ApplicationMetric(sampleConfigure.getSource()));
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,22 +22,25 @@ import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
|||
import org.apache.dubbo.config.MetricsConfig;
|
||||
import org.apache.dubbo.config.context.ConfigManager;
|
||||
import org.apache.dubbo.config.nested.HistogramConfig;
|
||||
import org.apache.dubbo.metrics.MetricsConstants;
|
||||
import org.apache.dubbo.metrics.MetricsGlobalRegistry;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.RTEvent;
|
||||
import org.apache.dubbo.metrics.listener.MetricsListener;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsListener;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.register.HistogramMetricRegister;
|
||||
import org.apache.dubbo.metrics.sample.HistogramMetricSample;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.RT;
|
||||
|
||||
public class HistogramMetricsCollector implements MetricsListener {
|
||||
public class HistogramMetricsCollector extends AbstractMetricsListener<RequestEvent> implements MetricsCollector<RequestEvent> {
|
||||
|
||||
private final ConcurrentHashMap<MethodMetric, Timer> rt = new ConcurrentHashMap<>();
|
||||
private HistogramMetricRegister metricRegister;
|
||||
|
|
@ -63,20 +66,28 @@ public class HistogramMetricsCollector implements MetricsListener {
|
|||
}
|
||||
|
||||
private void registerListener() {
|
||||
applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).addListener(this);
|
||||
applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).getEventMulticaster().addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(MetricsEvent event) {
|
||||
if (event instanceof RTEvent) {
|
||||
onRTEvent((RTEvent) event);
|
||||
}
|
||||
public void onEvent(RequestEvent event) {
|
||||
|
||||
}
|
||||
|
||||
private void onRTEvent(RTEvent event) {
|
||||
@Override
|
||||
public void onEventFinish(RequestEvent event) {
|
||||
onRTEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventError(RequestEvent event) {
|
||||
onRTEvent(event);
|
||||
}
|
||||
|
||||
private void onRTEvent(RequestEvent event) {
|
||||
if (metricRegister != null) {
|
||||
MethodMetric metric = (MethodMetric) event.getMetric();
|
||||
Long responseTime = event.getRt();
|
||||
MethodMetric metric = new MethodMetric(applicationModel.getApplicationName(), event.getAttachmentValue(MetricsConstants.INVOCATION));
|
||||
long responseTime = event.getTimePair().calc();
|
||||
|
||||
HistogramMetricSample sample = new HistogramMetricSample(MetricsKey.METRIC_RT_HISTOGRAM.getNameByType(metric.getSide()),
|
||||
MetricsKey.METRIC_RT_HISTOGRAM.getDescription(), metric.getTags(), RT);
|
||||
|
|
@ -85,4 +96,9 @@ public class HistogramMetricsCollector implements MetricsListener {
|
|||
timer.record(responseTime, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetricSample> collect() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,133 +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.collector.sample;
|
||||
|
||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.MethodEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.RTEvent;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.Metric;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
|
||||
|
||||
public class MethodMetricsSampler extends SimpleMetricsCountSampler<Invocation, String, MethodMetric> {
|
||||
|
||||
private final DefaultMetricsCollector collector;
|
||||
|
||||
public MethodMetricsSampler(DefaultMetricsCollector collector) {
|
||||
this.collector = collector;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void countConfigure(
|
||||
MetricsCountSampleConfigurer<Invocation, String, MethodMetric> sampleConfigure) {
|
||||
sampleConfigure.configureMetrics(configure -> new MethodMetric(collector.getApplicationName(), configure.getSource()));
|
||||
sampleConfigure.configureEventHandler(configure -> collector.getEventMulticaster().publishEvent(new MethodEvent(collector.getApplicationModel(), configure.getMetric(),
|
||||
configure.getMetricName())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rtConfigure(
|
||||
MetricsCountSampleConfigurer<Invocation, String, MethodMetric> sampleConfigure) {
|
||||
sampleConfigure.configureMetrics(configure -> new MethodMetric(collector.getApplicationName(), configure.getSource()));
|
||||
sampleConfigure.configureEventHandler(configure -> collector.getEventMulticaster().publishEvent(new RTEvent(collector.getApplicationModel(), configure.getMetric(), configure.getRt())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetricSample> sample() {
|
||||
List<MetricSample> metricSamples = new ArrayList<>();
|
||||
|
||||
collect(metricSamples);
|
||||
metricSamples.addAll(
|
||||
this.collectRT(new MetricSampleFactory<MethodMetric, GaugeMetricSample<?>>() {
|
||||
@Override
|
||||
public <T> GaugeMetricSample<?> newInstance(MetricsKey key, MethodMetric metric, T value, ToDoubleFunction<T> apply) {
|
||||
return createGaugeMetricSample(key, metric, MetricsCategory.RT, value, apply);
|
||||
}
|
||||
}));
|
||||
|
||||
return metricSamples;
|
||||
}
|
||||
|
||||
private void collect(List<MetricSample> list) {
|
||||
collectBySide(list, PROVIDER_SIDE);
|
||||
collectBySide(list, CONSUMER_SIDE);
|
||||
}
|
||||
|
||||
private void collectBySide(List<MetricSample> list, String side) {
|
||||
count(list, MetricsEvent.Type.TOTAL.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS);
|
||||
count(list, MetricsEvent.Type.SUCCEED.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_SUCCEED);
|
||||
count(list, MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_FAILED);
|
||||
count(list, MetricsEvent.Type.PROCESSING.getNameByType(side), MetricSample.Type.GAUGE, MetricsKey.METRIC_REQUESTS_PROCESSING);
|
||||
count(list, MetricsEvent.Type.BUSINESS_FAILED.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUEST_BUSINESS_FAILED);
|
||||
count(list, MetricsEvent.Type.REQUEST_TIMEOUT.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_TIMEOUT);
|
||||
count(list, MetricsEvent.Type.REQUEST_LIMIT.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_LIMIT);
|
||||
count(list, MetricsEvent.Type.TOTAL_FAILED.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_TOTAL_FAILED);
|
||||
count(list, MetricsEvent.Type.NETWORK_EXCEPTION.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_NETWORK_FAILED);
|
||||
count(list, MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED);
|
||||
count(list, MetricsEvent.Type.CODEC_EXCEPTION.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_CODEC_FAILED);
|
||||
}
|
||||
|
||||
|
||||
private <T> GaugeMetricSample<T> createGaugeMetricSample(MetricsKey metricsKey,
|
||||
MethodMetric methodMetric,
|
||||
MetricsCategory metricsCategory,
|
||||
T value,
|
||||
ToDoubleFunction<T> apply) {
|
||||
return new GaugeMetricSample<>(
|
||||
metricsKey.getNameByType(methodMetric.getSide()),
|
||||
metricsKey.getDescription(),
|
||||
methodMetric.getTags(),
|
||||
metricsCategory,
|
||||
value,
|
||||
apply);
|
||||
}
|
||||
|
||||
private <T extends Metric> void count(List<MetricSample> list, String eventType, MetricSample.Type type, MetricsKey metricsKey) {
|
||||
getCount(eventType).filter(e -> !e.isEmpty())
|
||||
.ifPresent(map -> map.forEach((k, v) -> {
|
||||
if(type == MetricSample.Type.COUNTER){
|
||||
list.add(createCounterMetricSample(metricsKey, k, MetricsCategory.REQUESTS, v));
|
||||
}else if(type == MetricSample.Type.GAUGE){
|
||||
list.add(createGaugeMetricSample(metricsKey, k, MetricsCategory.REQUESTS, v, AtomicLong::get));
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
private MetricSample createCounterMetricSample(MetricsKey metricsKey, MethodMetric methodMetric, MetricsCategory metricsCategory, AtomicLong value) {
|
||||
return new CounterMetricSample<>(metricsKey.getNameByType(methodMetric.getSide()),
|
||||
metricsKey.getDescription(),
|
||||
methodMetric.getTags(), metricsCategory, value);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -52,20 +52,10 @@ public class MetricsCountSampleConfigurer<S,K,M extends Metric> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public MetricsCountSampleConfigurer<S,K,M> configureEventHandler(
|
||||
Consumer<MetricsCountSampleConfigurer<S,K,M>> fireEventHandler){
|
||||
this.fireEventHandler = fireEventHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public S getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public K getMetricName() {
|
||||
return metricName;
|
||||
}
|
||||
|
||||
public M getMetric() {
|
||||
return metric;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,36 +18,17 @@
|
|||
package org.apache.dubbo.metrics.collector.sample;
|
||||
|
||||
import org.apache.dubbo.metrics.model.Metric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
|
||||
public interface MetricsCountSampler<S, K, M extends Metric> extends MetricsSampler {
|
||||
|
||||
void inc(S source, K metricName);
|
||||
|
||||
void dec(S source, K metricName);
|
||||
|
||||
void incOnEvent(S source, K metricName);
|
||||
|
||||
void decOnEvent(S source, K metricName);
|
||||
|
||||
void addRT(S source, Long rt);
|
||||
|
||||
void addRT(S source, K metricName, Long rt);
|
||||
|
||||
Optional<ConcurrentMap<M, AtomicLong>> getCount(K metricName);
|
||||
|
||||
<R extends MetricSample> List<R> collectRT(MetricSampleFactory<M, R> factory);
|
||||
|
||||
<R extends MetricSample> List<R> collectRT(MetricSampleFactory<M, R> factory, K metricName);
|
||||
|
||||
interface MetricSampleFactory<M, R extends MetricSample> {
|
||||
<T> R newInstance(MetricsKey key, M metric, T value, ToDoubleFunction<T> apply);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,20 +18,13 @@
|
|||
package org.apache.dubbo.metrics.collector.sample;
|
||||
|
||||
import org.apache.dubbo.common.utils.Assert;
|
||||
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
||||
import org.apache.dubbo.metrics.model.Metric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicLongArray;
|
||||
import java.util.concurrent.atomic.LongAccumulator;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
|
|
@ -45,14 +38,6 @@ public abstract class SimpleMetricsCountSampler<S, K, M extends Metric>
|
|||
|
||||
private final ConcurrentMap<M, AtomicLong> EMPTY_COUNT = new ConcurrentHashMap<>();
|
||||
private final Map<K, ConcurrentMap<M, AtomicLong>> metricCounter = new ConcurrentHashMap<>();
|
||||
// lastRT, totalRT, rtCount, avgRT share a container, can utilize the system cache line
|
||||
private final ConcurrentMap<M, AtomicLongArray> rtSample = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<M, LongAccumulator> minRT = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<M, LongAccumulator> maxRT = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentMap<K, ConcurrentMap<M, AtomicLongArray>> rtGroupSample = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<K, ConcurrentMap<M, LongAccumulator>> groupMinRT = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<K, ConcurrentMap<M, LongAccumulator>> groupMaxRT = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void inc(S source, K metricName) {
|
||||
|
|
@ -62,14 +47,6 @@ public abstract class SimpleMetricsCountSampler<S, K, M extends Metric>
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dec(S source, K metricName) {
|
||||
doExecute(source, metricName, counter -> {
|
||||
counter.decrementAndGet();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incOnEvent(S source, K metricName) {
|
||||
doExecute(source, metricName, counter -> {
|
||||
|
|
@ -78,91 +55,6 @@ public abstract class SimpleMetricsCountSampler<S, K, M extends Metric>
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decOnEvent(S source, K metricName) {
|
||||
doExecute(source, metricName, counter -> {
|
||||
counter.decrementAndGet();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRT(S source, Long rt) {
|
||||
MetricsCountSampleConfigurer<S, K, M> sampleConfigure = new MetricsCountSampleConfigurer<>();
|
||||
sampleConfigure.setSource(source);
|
||||
|
||||
this.rtConfigure(sampleConfigure);
|
||||
|
||||
M metric = sampleConfigure.getMetric();
|
||||
|
||||
AtomicLongArray rtCalculator = ConcurrentHashMapUtils.computeIfAbsent(this.rtSample, metric, k -> new AtomicLongArray(4));
|
||||
|
||||
// set lastRT
|
||||
rtCalculator.set(0, rt);
|
||||
|
||||
// add to totalRT
|
||||
rtCalculator.addAndGet(1, rt);
|
||||
|
||||
// add to rtCount
|
||||
rtCalculator.incrementAndGet(2);
|
||||
|
||||
// calc avgRT. In order to reduce the amount of calculation, calculated when collect
|
||||
//rtArray.set(3, Math.floorDiv(rtArray.get(1), rtArray.get(2)));
|
||||
|
||||
LongAccumulator min = ConcurrentHashMapUtils.computeIfAbsent(minRT, metric, k -> new LongAccumulator(Long::min, Long.MAX_VALUE));
|
||||
min.accumulate(rt);
|
||||
|
||||
LongAccumulator max = ConcurrentHashMapUtils.computeIfAbsent(maxRT, metric, k -> new LongAccumulator(Long::max, Long.MIN_VALUE));
|
||||
max.accumulate(rt);
|
||||
|
||||
sampleConfigure.setRt(rt);
|
||||
|
||||
sampleConfigure.getFireEventHandler().accept(sampleConfigure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRT(S source, K metricName, Long rt) {
|
||||
MetricsCountSampleConfigurer<S, K, M> sampleConfigure = new MetricsCountSampleConfigurer<>();
|
||||
sampleConfigure.setSource(source);
|
||||
sampleConfigure.setMetricsName(metricName);
|
||||
|
||||
this.rtConfigure(sampleConfigure);
|
||||
|
||||
M metric = sampleConfigure.getMetric();
|
||||
|
||||
ConcurrentMap<M, AtomicLongArray> nameToCalculator = rtGroupSample.get(metricName);
|
||||
|
||||
if (nameToCalculator == null) {
|
||||
ConcurrentHashMap<M, AtomicLongArray> calculator = new ConcurrentHashMap<>();
|
||||
calculator.put(metric, new AtomicLongArray(4));
|
||||
|
||||
rtGroupSample.put(metricName, calculator);
|
||||
|
||||
nameToCalculator = rtGroupSample.get(metricName);
|
||||
}
|
||||
AtomicLongArray calculator = nameToCalculator.get(metric);
|
||||
|
||||
// set lastRT
|
||||
calculator.set(0, rt);
|
||||
|
||||
// add to totalRT
|
||||
calculator.addAndGet(1, rt);
|
||||
|
||||
// add to rtCount
|
||||
calculator.incrementAndGet(2);
|
||||
|
||||
ConcurrentMap<M, LongAccumulator> minRT = ConcurrentHashMapUtils.computeIfAbsent(groupMinRT, metricName, k -> new ConcurrentHashMap<>());
|
||||
LongAccumulator min = ConcurrentHashMapUtils.computeIfAbsent(minRT, metric, k -> new LongAccumulator(Long::min, Long.MAX_VALUE));
|
||||
min.accumulate(rt);
|
||||
|
||||
ConcurrentMap<M, LongAccumulator> maxRT = ConcurrentHashMapUtils.computeIfAbsent(groupMaxRT, metricName, k -> new ConcurrentHashMap<>());
|
||||
LongAccumulator max = ConcurrentHashMapUtils.computeIfAbsent(maxRT, metric, k -> new LongAccumulator(Long::max, Long.MIN_VALUE));
|
||||
max.accumulate(rt);
|
||||
sampleConfigure.setRt(rt);
|
||||
|
||||
sampleConfigure.getFireEventHandler().accept(sampleConfigure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ConcurrentMap<M, AtomicLong>> getCount(K metricName) {
|
||||
return Optional.ofNullable(metricCounter.get(metricName) == null ?
|
||||
|
|
@ -170,42 +62,6 @@ public abstract class SimpleMetricsCountSampler<S, K, M extends Metric>
|
|||
metricCounter.get(metricName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R extends MetricSample> List<R> collectRT(MetricSampleFactory<M, R> factory) {
|
||||
return collect(factory, rtSample, this.minRT, this.maxRT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R extends MetricSample> List<R> collectRT(MetricSampleFactory<M, R> factory, K metricName) {
|
||||
return collect(factory, rtGroupSample.get(metricName), groupMinRT.get(metricName), groupMaxRT.get(metricName));
|
||||
}
|
||||
|
||||
private <R extends MetricSample> List<R> collect(MetricSampleFactory<M, R> factory,
|
||||
ConcurrentMap<M, AtomicLongArray> rtSample,
|
||||
ConcurrentMap<M, LongAccumulator> min,
|
||||
ConcurrentMap<M, LongAccumulator> max) {
|
||||
final List<R> result = new ArrayList<>();
|
||||
rtSample.forEach((k, v) -> {
|
||||
// lastRT
|
||||
result.add(factory.newInstance(MetricsKey.METRIC_RT_LAST, k, v, value -> value.get(0)));
|
||||
// totalRT
|
||||
result.add(factory.newInstance(MetricsKey.METRIC_RT_SUM, k, v, value -> value.get(1)));
|
||||
// avgRT
|
||||
result.add(factory.newInstance(MetricsKey.METRIC_RT_AVG, k, v, value -> Math.floorDiv(value.get(1), value.get(2))));
|
||||
});
|
||||
|
||||
min.forEach((k, v) ->
|
||||
result.add(factory.newInstance(MetricsKey.METRIC_RT_MIN, k, v, LongAccumulator::get)));
|
||||
|
||||
max.forEach((k, v) ->
|
||||
result.add(factory.newInstance(MetricsKey.METRIC_RT_MAX, k, v, LongAccumulator::get)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void rtConfigure(MetricsCountSampleConfigurer<S, K, M> configure) {
|
||||
}
|
||||
|
||||
protected abstract void countConfigure(MetricsCountSampleConfigurer<S, K, M> sampleConfigure);
|
||||
|
||||
private void doExecute(S source, K metricsName, Function<AtomicLong, Boolean> counter) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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.event;
|
||||
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.metrics.MetricsConstants;
|
||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
||||
import org.apache.dubbo.metrics.collector.MethodMetricsCollector;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener;
|
||||
import org.apache.dubbo.metrics.listener.MetricsListener;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.key.CategoryOverall;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsCat;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION_METRICS_COUNTER;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public final class DefaultSubDispatcher extends SimpleMetricsEventMulticaster {
|
||||
|
||||
public DefaultSubDispatcher(DefaultMetricsCollector collector) {
|
||||
|
||||
CategoryOverall categoryOverall = initMethodRequest();
|
||||
super.addListener(categoryOverall.getPost().getEventFunc().apply(collector));
|
||||
super.addListener(categoryOverall.getFinish().getEventFunc().apply(collector));
|
||||
super.addListener(categoryOverall.getError().getEventFunc().apply(collector));
|
||||
|
||||
super.addListener(new MetricsListener<RequestBeforeEvent>() {
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RequestBeforeEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(RequestBeforeEvent event) {
|
||||
MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD);
|
||||
MetricsSupport.increment(METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED, dynamicPlaceType, (MethodMetricsCollector) collector, event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private CategoryOverall initMethodRequest() {
|
||||
|
||||
return new CategoryOverall(null,
|
||||
new MetricsCat(MetricsKey.METRIC_REQUESTS, (key, placeType, collector) -> AbstractMetricsKeyListener.onEvent(key,
|
||||
event ->
|
||||
{
|
||||
MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.METHOD);
|
||||
MetricsSupport.increment(key, dynamicPlaceType, (MethodMetricsCollector) collector, event);
|
||||
|
||||
// METRIC_REQUESTS_PROCESSING use GAUGE
|
||||
Invocation invocation = event.getAttachmentValue(INVOCATION);
|
||||
invocation.put(INVOCATION_METRICS_COUNTER, MetricSample.Type.GAUGE);
|
||||
MetricsSupport.increment(MetricsKey.METRIC_REQUESTS_PROCESSING, dynamicPlaceType, (MethodMetricsCollector) collector, event);
|
||||
})),
|
||||
new MetricsCat(MetricsKey.METRIC_REQUESTS_SUCCEED, (key, placeType, collector) -> AbstractMetricsKeyListener.onFinish(key,
|
||||
event ->
|
||||
{
|
||||
MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.METHOD);
|
||||
MetricsSupport.dec(MetricsKey.METRIC_REQUESTS_PROCESSING, dynamicPlaceType, (MethodMetricsCollector) collector, event);
|
||||
|
||||
Object throwableObj = event.getAttachmentValue(METRIC_THROWABLE);
|
||||
MetricsKey targetKey;
|
||||
if (throwableObj == null) {
|
||||
targetKey = key;
|
||||
} else {
|
||||
targetKey = MetricsSupport.getMetricsKey((RpcException) throwableObj);
|
||||
}
|
||||
MetricsSupport.incrAndAddRt(targetKey, dynamicPlaceType, (MethodMetricsCollector) collector, event);
|
||||
})),
|
||||
new MetricsCat(MetricsKey.METRIC_REQUEST_BUSINESS_FAILED, (key, placeType, collector) -> AbstractMetricsKeyListener.onError(key,
|
||||
event ->
|
||||
{
|
||||
Throwable throwable = event.getAttachmentValue(METRIC_THROWABLE);
|
||||
MetricsKey targetKey = MetricsKey.METRIC_REQUESTS_FAILED_AGG;
|
||||
if (throwable instanceof RpcException) {
|
||||
targetKey = MetricsSupport.getMetricsKey((RpcException) throwable);
|
||||
}
|
||||
// Dynamic metricsKey && dynamicPlaceType
|
||||
MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.METHOD);
|
||||
MetricsSupport.increment(MetricsKey.METRIC_REQUESTS_TOTAL_FAILED, dynamicPlaceType, (MethodMetricsCollector) collector, event);
|
||||
MetricsSupport.dec(MetricsKey.METRIC_REQUESTS_PROCESSING, dynamicPlaceType, (MethodMetricsCollector) collector, event);
|
||||
MetricsSupport.incrAndAddRt(targetKey, dynamicPlaceType, (MethodMetricsCollector) collector, event);
|
||||
}
|
||||
)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.event;
|
||||
|
||||
import org.apache.dubbo.metrics.MetricsConstants;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
|
||||
|
||||
/**
|
||||
* Acts on MetricsClusterFilter to monitor exceptions that occur before request execution
|
||||
*/
|
||||
public class RequestBeforeEvent extends TimeCounterEvent {
|
||||
|
||||
public RequestBeforeEvent(ApplicationModel source, TypeWrapper typeWrapper) {
|
||||
super(source, typeWrapper);
|
||||
|
||||
}
|
||||
|
||||
public static RequestBeforeEvent toEvent(ApplicationModel applicationModel, Invocation invocation) {
|
||||
RequestBeforeEvent event = new RequestBeforeEvent(applicationModel, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
|
||||
event.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
|
||||
event.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation));
|
||||
event.putAttachment(MetricsConstants.INVOCATION, invocation);
|
||||
return event;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.event;
|
||||
|
||||
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||
import org.apache.dubbo.metrics.MetricsConstants;
|
||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
||||
import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SUCCEED;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUEST_BUSINESS_FAILED;
|
||||
|
||||
/**
|
||||
* Request related events
|
||||
*/
|
||||
public class RequestEvent extends TimeCounterEvent {
|
||||
public RequestEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
|
||||
super(applicationModel,typeWrapper);
|
||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||
DefaultMetricsCollector collector;
|
||||
if (!beanFactory.isDestroyed()) {
|
||||
collector = beanFactory.getBean(DefaultMetricsCollector.class);
|
||||
super.setAvailable(collector != null && collector.isCollectEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
public static RequestEvent toRequestEvent(ApplicationModel applicationModel, Invocation invocation) {
|
||||
RequestEvent requestEvent = new RequestEvent(applicationModel, new TypeWrapper(MetricsLevel.SERVICE, METRIC_REQUESTS, METRIC_REQUESTS_SUCCEED, METRIC_REQUEST_BUSINESS_FAILED)) {
|
||||
@Override
|
||||
public void customAfterPost(Object postResult) {
|
||||
if (postResult == null) {
|
||||
return;
|
||||
}
|
||||
if (!(postResult instanceof Result)) {
|
||||
throw new MetricsNeverHappenException("Result type error, postResult:" + postResult.getClass().getName());
|
||||
}
|
||||
super.putAttachment(METRIC_THROWABLE, ((Result) postResult).getException());
|
||||
}
|
||||
};
|
||||
requestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
|
||||
requestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
|
||||
requestEvent.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation));
|
||||
return requestEvent;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,110 +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.filter;
|
||||
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.metrics.collector.sample.MethodMetricsSampler;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.METRIC_FILTER_START_TIME;
|
||||
|
||||
public class MethodMetricsInterceptor {
|
||||
|
||||
private final MethodMetricsSampler sampler;
|
||||
|
||||
public MethodMetricsInterceptor(MethodMetricsSampler sampler) {
|
||||
this.sampler = sampler;
|
||||
}
|
||||
|
||||
public void beforeMethod(Invocation invocation) {
|
||||
String side = getSide(invocation);
|
||||
sampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL.getNameByType(side));
|
||||
sampler.incOnEvent(invocation, MetricsEvent.Type.PROCESSING.getNameByType(side));
|
||||
invocation.put(METRIC_FILTER_START_TIME, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
private String getSide(Invocation invocation) {
|
||||
Optional<? extends Invoker<?>> invoker = Optional.ofNullable(invocation.getInvoker());
|
||||
return invoker.isPresent() ? invoker.get().getUrl().getSide() : PROVIDER_SIDE;
|
||||
}
|
||||
|
||||
public void afterMethod(Invocation invocation, Result result) {
|
||||
if (result.hasException()) {
|
||||
handleMethodException(invocation, result.getException(), true);
|
||||
} else {
|
||||
sampler.incOnEvent(invocation, MetricsEvent.Type.SUCCEED.getNameByType(getSide(invocation)));
|
||||
onCompleted(invocation);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleMethodException(Invocation invocation, Throwable throwable, boolean isBusiness) {
|
||||
if (throwable == null) {
|
||||
return;
|
||||
}
|
||||
String side = getSide(invocation);
|
||||
|
||||
MetricsEvent.Type eventType = MetricsEvent.Type.UNKNOWN_FAILED;
|
||||
if (isBusiness) {
|
||||
eventType = MetricsEvent.Type.BUSINESS_FAILED;
|
||||
} else if (throwable instanceof RpcException) {
|
||||
RpcException e = (RpcException) throwable;
|
||||
|
||||
if (e.isTimeout()) {
|
||||
eventType = MetricsEvent.Type.REQUEST_TIMEOUT;
|
||||
}
|
||||
if (e.isLimitExceed()) {
|
||||
eventType = MetricsEvent.Type.REQUEST_LIMIT;
|
||||
}
|
||||
if (e.isBiz()) {
|
||||
eventType = MetricsEvent.Type.BUSINESS_FAILED;
|
||||
}
|
||||
if (e.isSerialization()) {
|
||||
eventType = MetricsEvent.Type.CODEC_EXCEPTION;
|
||||
}
|
||||
if (e.isNetwork()) {
|
||||
eventType = MetricsEvent.Type.NETWORK_EXCEPTION;
|
||||
}
|
||||
if (e.isNoInvokerAvailableAfterFilter() && CommonConstants.CONSUMER_SIDE.equals(side)) {
|
||||
eventType = MetricsEvent.Type.NO_INVOKER_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
sampler.incOnEvent(invocation, eventType.getNameByType(side));
|
||||
onCompleted(invocation);
|
||||
sampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL_FAILED.getNameByType(side));
|
||||
}
|
||||
|
||||
private void rtTime(Invocation invocation) {
|
||||
Long endTime = System.currentTimeMillis();
|
||||
Long beginTime = (Long) invocation.get(METRIC_FILTER_START_TIME);
|
||||
Long rt = endTime - beginTime;
|
||||
sampler.addRT(invocation, rt);
|
||||
}
|
||||
|
||||
private void onCompleted(Invocation invocation) {
|
||||
rtTime(invocation);
|
||||
sampler.dec(invocation, MetricsEvent.Type.PROCESSING.getNameByType(getSide(invocation)));
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,8 @@ package org.apache.dubbo.metrics.filter;
|
|||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.rpc.BaseFilter;
|
||||
import org.apache.dubbo.rpc.Filter;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
|
@ -32,61 +33,57 @@ import org.apache.dubbo.rpc.model.ScopeModelAware;
|
|||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.METRIC_FILTER_EVENT;
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE;
|
||||
|
||||
@Activate(group = {CONSUMER, PROVIDER}, order = Integer.MIN_VALUE + 100)
|
||||
public class MetricsFilter implements Filter, BaseFilter.Listener, ScopeModelAware {
|
||||
|
||||
private ApplicationModel applicationModel;
|
||||
private final static ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(MetricsFilter.class);
|
||||
|
||||
private DefaultMetricsCollector collector = null;
|
||||
private MethodMetricsInterceptor metricsInterceptor;
|
||||
|
||||
@Override
|
||||
public void setApplicationModel(ApplicationModel applicationModel) {
|
||||
collector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
|
||||
|
||||
if (collector != null) {
|
||||
metricsInterceptor = new MethodMetricsInterceptor(collector.getMethodSampler());
|
||||
}
|
||||
this.applicationModel = applicationModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
||||
if (collector == null || !collector.isCollectEnabled()) {
|
||||
return invoker.invoke(invocation);
|
||||
}
|
||||
|
||||
try {
|
||||
metricsInterceptor.beforeMethod(invocation);
|
||||
RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, invocation);
|
||||
MetricsEventBus.before(requestEvent, () -> invocation.put(METRIC_FILTER_EVENT, requestEvent));
|
||||
} catch (Throwable t) {
|
||||
LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when beforeMethod.", t);
|
||||
LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when invoke.", t);
|
||||
}
|
||||
|
||||
return invoker.invoke(invocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Result result, Invoker<?> invoker, Invocation invocation) {
|
||||
if (collector == null || !collector.isCollectEnabled()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
metricsInterceptor.afterMethod(invocation, result);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when afterMethod.", t);
|
||||
Object eventObj = invocation.get(METRIC_FILTER_EVENT);
|
||||
if (eventObj != null) {
|
||||
try {
|
||||
MetricsEventBus.after((RequestEvent) eventObj, result);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when onResponse.", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
|
||||
if (collector == null || !collector.isCollectEnabled()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
metricsInterceptor.handleMethodException(invocation, t, false);
|
||||
} catch (Throwable t1) {
|
||||
LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when handleMethodException.", t1);
|
||||
Object eventObj = invocation.get(METRIC_FILTER_EVENT);
|
||||
if (eventObj != null) {
|
||||
try {
|
||||
RequestEvent requestEvent = (RequestEvent) eventObj;
|
||||
requestEvent.putAttachment(METRIC_THROWABLE, t);
|
||||
MetricsEventBus.error(requestEvent);
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when onResponse.", throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
default-collector=org.apache.dubbo.metrics.collector.DefaultMetricsCollector
|
||||
|
|
@ -25,19 +25,29 @@ import org.apache.dubbo.config.ApplicationConfig;
|
|||
import org.apache.dubbo.config.MetricsConfig;
|
||||
import org.apache.dubbo.config.context.ConfigManager;
|
||||
import org.apache.dubbo.config.nested.AggregationConfig;
|
||||
import org.apache.dubbo.metrics.MetricsConstants;
|
||||
import org.apache.dubbo.metrics.TestMetricsInvoker;
|
||||
import org.apache.dubbo.metrics.aggregate.TimeWindowCounter;
|
||||
import org.apache.dubbo.metrics.collector.sample.MethodMetricsSampler;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.RTEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.event.RequestBeforeEvent;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.metrics.filter.MetricsFilter;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.TimePair;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.AppResponse;
|
||||
import org.apache.dubbo.rpc.AsyncRpcResult;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
@ -57,9 +67,9 @@ import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
|
|||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.QPS;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class AggregateMetricsCollectorTest {
|
||||
|
|
@ -72,6 +82,9 @@ class AggregateMetricsCollectorTest {
|
|||
private String version;
|
||||
private RpcInvocation invocation;
|
||||
private String side;
|
||||
private MetricsDispatcher metricsDispatcher;
|
||||
private AggregateMetricsCollector collector;
|
||||
private MetricsFilter metricsFilter;
|
||||
|
||||
public static MethodMetric getTestMethodMetric() {
|
||||
|
||||
|
|
@ -86,36 +99,13 @@ class AggregateMetricsCollectorTest {
|
|||
return methodMetric;
|
||||
}
|
||||
|
||||
public static AggregateMetricsCollector getTestCollector() {
|
||||
|
||||
ApplicationModel applicationModel = mock(ApplicationModel.class);
|
||||
ConfigManager configManager = new ConfigManager(applicationModel);
|
||||
MetricsConfig metricsConfig = spy(new MetricsConfig());
|
||||
|
||||
configManager.setMetrics(metricsConfig);
|
||||
|
||||
AggregationConfig aggregationConfig = spy(new AggregationConfig());
|
||||
when(aggregationConfig.getEnabled()).thenReturn(true);
|
||||
when(metricsConfig.getAggregation()).thenReturn(aggregationConfig);
|
||||
when(applicationModel.getApplicationConfigManager()).thenReturn(configManager);
|
||||
|
||||
ScopeBeanFactory beanFactory = mock(ScopeBeanFactory.class);
|
||||
when(beanFactory.getBean(DefaultMetricsCollector.class)).thenReturn(new DefaultMetricsCollector());
|
||||
when(applicationModel.getBeanFactory()).thenReturn(beanFactory);
|
||||
|
||||
return new AggregateMetricsCollector(applicationModel);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
applicationModel = ApplicationModel.defaultModel();
|
||||
ApplicationConfig config = new ApplicationConfig();
|
||||
config.setName("MockMetrics");
|
||||
|
||||
applicationModel = ApplicationModel.defaultModel();
|
||||
applicationModel.getApplicationConfigManager().setApplication(config);
|
||||
|
||||
defaultCollector = new DefaultMetricsCollector();
|
||||
defaultCollector.setCollectEnabled(true);
|
||||
MetricsConfig metricsConfig = new MetricsConfig();
|
||||
AggregationConfig aggregationConfig = new AggregationConfig();
|
||||
aggregationConfig.setEnabled(true);
|
||||
|
|
@ -123,7 +113,16 @@ class AggregateMetricsCollectorTest {
|
|||
aggregationConfig.setTimeWindowSeconds(120);
|
||||
metricsConfig.setAggregation(aggregationConfig);
|
||||
applicationModel.getApplicationConfigManager().setMetrics(metricsConfig);
|
||||
metricsDispatcher = applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class);
|
||||
defaultCollector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
|
||||
collector = applicationModel.getBeanFactory().getOrRegisterBean(AggregateMetricsCollector.class);
|
||||
collector.setCollectEnabled(true);
|
||||
|
||||
defaultCollector = new DefaultMetricsCollector();
|
||||
defaultCollector.setCollectEnabled(true);
|
||||
|
||||
metricsFilter = new MetricsFilter();
|
||||
metricsFilter.setApplicationModel(applicationModel);
|
||||
|
||||
interfaceName = "org.apache.dubbo.MockInterface";
|
||||
methodName = "mockMethod";
|
||||
|
|
@ -135,10 +134,20 @@ class AggregateMetricsCollectorTest {
|
|||
invocation.setAttachment(VERSION_KEY, version);
|
||||
side = CommonConstants.CONSUMER;
|
||||
invocation.setInvoker(new TestMetricsInvoker(side));
|
||||
invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version);
|
||||
RpcContext.getServiceContext().setUrl(URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&side=" + side));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListener() {
|
||||
AggregateMetricsCollector metricsCollector = new AggregateMetricsCollector(applicationModel);
|
||||
RequestEvent event = RequestEvent.toRequestEvent(applicationModel, invocation);
|
||||
RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
|
||||
Assertions.assertTrue(metricsCollector.isSupport(event));
|
||||
Assertions.assertFalse(metricsCollector.isSupport(beforeEvent));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
applicationModel.destroy();
|
||||
|
|
@ -147,19 +156,20 @@ class AggregateMetricsCollectorTest {
|
|||
@Test
|
||||
void testRequestsMetrics() {
|
||||
String applicationName = applicationModel.getApplicationName();
|
||||
AggregateMetricsCollector collector = new AggregateMetricsCollector(applicationModel);
|
||||
|
||||
defaultCollector.setApplicationName(applicationName);
|
||||
MethodMetricsSampler methodMetricsCountSampler = defaultCollector.getMethodSampler();
|
||||
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.SUCCEED.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.BUSINESS_FAILED.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.NETWORK_EXCEPTION.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.CODEC_EXCEPTION.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.NO_INVOKER_AVAILABLE.getNameByType(side));
|
||||
metricsFilter.invoke(new TestMetricsInvoker(side), invocation);
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
AppResponse mockRpcResult = new AppResponse();
|
||||
mockRpcResult.setException(new RpcException(RpcException.NETWORK_EXCEPTION));
|
||||
Result result = AsyncRpcResult.newDefaultAsyncResult(mockRpcResult, invocation);
|
||||
metricsFilter.onResponse(result, new TestMetricsInvoker(side), invocation);
|
||||
|
||||
|
||||
|
||||
List<MetricSample> samples = collector.collect();
|
||||
|
|
@ -177,46 +187,10 @@ class AggregateMetricsCollectorTest {
|
|||
@SuppressWarnings("rawtypes")
|
||||
Map<String, Long> sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> ((GaugeMetricSample) k).applyAsLong()));
|
||||
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_TOTAL_AGG.getNameByType(side)), 1L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_SUCCEED_AGG.getNameByType(side)), 1L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_FAILED_AGG.getNameByType(side)), 1L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_BUSINESS_FAILED_AGG.getNameByType(side)), 1L);
|
||||
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_TOTAL_NETWORK_FAILED_AGG.getNameByType(side)), 1L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_TOTAL_CODEC_FAILED_AGG.getNameByType(side)), 1L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG.getNameByType(side)), 1L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.INVOKER_NO_AVAILABLE_COUNT.getNameByType(side)), 1L);
|
||||
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_NETWORK_FAILED_AGG.getNameByType(side)), 1L);
|
||||
Assertions.assertTrue(sampleMap.containsKey(MetricsKey.METRIC_QPS.getNameByType(side)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRTMetrics() {
|
||||
AggregateMetricsCollector collector = new AggregateMetricsCollector(applicationModel);
|
||||
|
||||
defaultCollector.setApplicationName(applicationModel.getApplicationName());
|
||||
|
||||
MethodMetricsSampler methodMetricsCountSampler = defaultCollector.getMethodSampler();
|
||||
|
||||
methodMetricsCountSampler.addRT(invocation, 10L);
|
||||
|
||||
List<MetricSample> samples = collector.collect();
|
||||
for (MetricSample sample : samples) {
|
||||
Map<String, String> tags = sample.getTags();
|
||||
|
||||
Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName);
|
||||
Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName);
|
||||
Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group);
|
||||
Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<String, Long> sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> ((GaugeMetricSample) k).applyAsLong()));
|
||||
|
||||
Assertions.assertTrue(sampleMap.containsKey(MetricsKey.METRIC_RT_P99.getNameByType(side)));
|
||||
Assertions.assertTrue(sampleMap.containsKey(MetricsKey.METRIC_RT_P95.getNameByType(side)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQPS() {
|
||||
ApplicationModel applicationModel = mock(ApplicationModel.class);
|
||||
|
|
@ -262,13 +236,18 @@ class AggregateMetricsCollectorTest {
|
|||
|
||||
@Test
|
||||
void testP95AndP99() throws InterruptedException {
|
||||
AggregateMetricsCollector collector = getTestCollector();
|
||||
MethodMetric methodMetric = getTestMethodMetric();
|
||||
|
||||
List<Double> requestTimes = new ArrayList<>(10000);
|
||||
metricsDispatcher.addListener(collector);
|
||||
ConfigManager configManager = applicationModel.getApplicationConfigManager();
|
||||
MetricsConfig config = configManager.getMetrics().orElse(null);
|
||||
AggregationConfig aggregationConfig = new AggregationConfig();
|
||||
aggregationConfig.setEnabled(true);
|
||||
config.setAggregation(aggregationConfig);
|
||||
|
||||
List<Long> requestTimes = new ArrayList<>(10000);
|
||||
|
||||
for (int i = 0; i < 300; i++) {
|
||||
requestTimes.add(1000 * Math.random());
|
||||
requestTimes.add(Double.valueOf(1000 * Math.random()).longValue());
|
||||
}
|
||||
|
||||
Collections.sort(requestTimes);
|
||||
|
|
@ -278,8 +257,14 @@ class AggregateMetricsCollectorTest {
|
|||
double manualP95 = requestTimes.get((int) Math.round(p95Index));
|
||||
double manualP99 = requestTimes.get((int) Math.round(p99Index));
|
||||
|
||||
for (Double requestTime : requestTimes) {
|
||||
collector.onEvent(new RTEvent(applicationModel, methodMetric, requestTime.longValue()));
|
||||
for (Long requestTime : requestTimes) {
|
||||
RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, invocation);
|
||||
TestRequestEvent testRequestEvent = new TestRequestEvent(requestEvent.getSource(), requestEvent.getTypeWrapper());
|
||||
testRequestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
|
||||
testRequestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
|
||||
testRequestEvent.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation));
|
||||
testRequestEvent.setRt(requestTime);
|
||||
MetricsEventBus.post(testRequestEvent, () -> null);
|
||||
}
|
||||
Thread.sleep(4000L);
|
||||
|
||||
|
|
@ -304,9 +289,42 @@ class AggregateMetricsCollectorTest {
|
|||
double p99 = p99Sample.applyAsDouble();
|
||||
|
||||
//An error of less than 5% is allowed
|
||||
System.out.println(Math.abs(1 - p95 / manualP95));
|
||||
Assertions.assertTrue(Math.abs(1 - p95 / manualP95) < 0.05);
|
||||
Assertions.assertTrue(Math.abs(1 - p99 / manualP99) < 0.05);
|
||||
}
|
||||
|
||||
public static class TestRequestEvent extends RequestEvent {
|
||||
private long rt;
|
||||
|
||||
public TestRequestEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
|
||||
super(applicationModel, typeWrapper);
|
||||
}
|
||||
|
||||
public void setRt(long rt) {
|
||||
this.rt = rt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePair getTimePair() {
|
||||
return new TestTimePair(rt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TestTimePair extends TimePair {
|
||||
|
||||
long rt;
|
||||
|
||||
public TestTimePair(long rt) {
|
||||
super(rt);
|
||||
this.rt = rt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long calc() {
|
||||
return this.rt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* 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.collector;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.metrics.TestMetricsInvoker;
|
||||
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
||||
import org.apache.dubbo.metrics.event.RequestBeforeEvent;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.metrics.filter.MetricsFilter;
|
||||
import org.apache.dubbo.metrics.model.ServiceKeyMetric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.AppResponse;
|
||||
import org.apache.dubbo.rpc.AsyncRpcResult;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.METRIC_FILTER_EVENT;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_PROCESSING;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SUCCEED;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_TIMEOUT;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_TOTAL_FAILED;
|
||||
|
||||
|
||||
class DefaultCollectorTest {
|
||||
|
||||
private ApplicationModel applicationModel;
|
||||
|
||||
private String interfaceName;
|
||||
private String methodName;
|
||||
private String group;
|
||||
private String version;
|
||||
private RpcInvocation invocation;
|
||||
private String side;
|
||||
|
||||
MetricsDispatcher metricsDispatcher;
|
||||
DefaultMetricsCollector defaultCollector;
|
||||
|
||||
MetricsFilter metricsFilter;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
FrameworkModel frameworkModel = FrameworkModel.defaultModel();
|
||||
applicationModel = frameworkModel.newApplication();
|
||||
ApplicationConfig config = new ApplicationConfig();
|
||||
config.setName("MockMetrics");
|
||||
|
||||
applicationModel.getApplicationConfigManager().setApplication(config);
|
||||
metricsDispatcher = applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class);
|
||||
defaultCollector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
|
||||
defaultCollector.setCollectEnabled(true);
|
||||
|
||||
interfaceName = "org.apache.dubbo.MockInterface";
|
||||
methodName = "mockMethod";
|
||||
group = "mockGroup";
|
||||
version = "1.0.0";
|
||||
invocation = new RpcInvocation(methodName, interfaceName, "serviceKey", null, null);
|
||||
invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version);
|
||||
invocation.setAttachment(GROUP_KEY, group);
|
||||
invocation.setAttachment(VERSION_KEY, version);
|
||||
side = CommonConstants.CONSUMER;
|
||||
invocation.setInvoker(new TestMetricsInvoker(side));
|
||||
invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version);
|
||||
RpcContext.getServiceContext().setUrl(URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&side=" + side));
|
||||
|
||||
metricsFilter = new MetricsFilter();
|
||||
metricsFilter.setApplicationModel(applicationModel);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListener() {
|
||||
DefaultMetricsCollector metricsCollector = new DefaultMetricsCollector();
|
||||
RequestEvent event = RequestEvent.toRequestEvent(applicationModel, invocation);
|
||||
RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
|
||||
Assertions.assertTrue(metricsCollector.isSupport(event));
|
||||
Assertions.assertTrue(metricsCollector.isSupport(beforeEvent));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
applicationModel.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* No rt metrics because Aggregate calc
|
||||
*/
|
||||
@Test
|
||||
void testRequestEventNoRt() {
|
||||
|
||||
applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class);
|
||||
DefaultMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class);
|
||||
collector.setCollectEnabled(true);
|
||||
|
||||
metricsFilter.invoke(new TestMetricsInvoker(side), invocation);
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
AppResponse mockRpcResult = new AppResponse();
|
||||
// mockRpcResult.setException(new RpcException("hessian"));
|
||||
Result result = AsyncRpcResult.newDefaultAsyncResult(mockRpcResult, invocation);
|
||||
metricsFilter.onResponse(result, new TestMetricsInvoker(side), invocation);
|
||||
|
||||
RequestEvent eventObj = (RequestEvent) invocation.get(METRIC_FILTER_EVENT);
|
||||
long c1 = eventObj.getTimePair().calc();
|
||||
|
||||
// push finish rt +1
|
||||
List<MetricSample> metricSamples = collector.collect();
|
||||
//num(total+success+processing) + rt(5) = 8
|
||||
Assertions.assertEquals(8, metricSamples.size());
|
||||
List<String> metricsNames = metricSamples.stream().map(MetricSample::getName).collect(Collectors.toList());
|
||||
// No error will contain total+success+processing
|
||||
String REQUESTS = new MetricsKeyWrapper(METRIC_REQUESTS, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
String SUCCEED = new MetricsKeyWrapper(METRIC_REQUESTS_SUCCEED, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
String PROCESSING = new MetricsKeyWrapper(METRIC_REQUESTS_PROCESSING, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
Assertions.assertTrue(metricsNames.contains(REQUESTS));
|
||||
Assertions.assertTrue(metricsNames.contains(SUCCEED));
|
||||
Assertions.assertTrue(metricsNames.contains(PROCESSING));
|
||||
for (MetricSample metricSample : metricSamples) {
|
||||
if (metricSample instanceof GaugeMetricSample) {
|
||||
GaugeMetricSample<?> gaugeMetricSample = (GaugeMetricSample<?>) metricSample;
|
||||
Object objVal = gaugeMetricSample.getValue();
|
||||
if (objVal instanceof Map) {
|
||||
Map<ServiceKeyMetric, AtomicLong> value = (Map<ServiceKeyMetric, AtomicLong>) objVal;
|
||||
if (metricSample.getName().equals(REQUESTS)) {
|
||||
Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 1));
|
||||
}
|
||||
if (metricSample.getName().equals(PROCESSING)) {
|
||||
Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 0));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AtomicLong value = (AtomicLong) ((CounterMetricSample<?>) metricSample).getValue();
|
||||
if (metricSample.getName().equals(SUCCEED)) {
|
||||
Assertions.assertEquals(1, value.intValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
metricsFilter.invoke(new TestMetricsInvoker(side), invocation);
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
metricsFilter.onError(new RpcException(RpcException.TIMEOUT_EXCEPTION, "timeout"), new TestMetricsInvoker(side), invocation);
|
||||
eventObj = (RequestEvent) invocation.get(METRIC_FILTER_EVENT);
|
||||
long c2 = eventObj.getTimePair().calc();
|
||||
metricSamples = collector.collect();
|
||||
|
||||
// num(total+success+error+total_error+processing) + rt(5) = 5
|
||||
Assertions.assertEquals(10, metricSamples.size());
|
||||
|
||||
String TIMEOUT = new MetricsKeyWrapper(METRIC_REQUESTS_TIMEOUT, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
String TOTAL_FAILED = new MetricsKeyWrapper(METRIC_REQUESTS_TOTAL_FAILED, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
for (MetricSample metricSample : metricSamples) {
|
||||
if (metricSample instanceof GaugeMetricSample) {
|
||||
GaugeMetricSample<?> gaugeMetricSample = (GaugeMetricSample<?>) metricSample;
|
||||
Object objVal = gaugeMetricSample.getValue();
|
||||
if (objVal instanceof Map) {
|
||||
Map<ServiceKeyMetric, AtomicLong> value = (Map<ServiceKeyMetric, AtomicLong>) ((GaugeMetricSample<?>) metricSample).getValue();
|
||||
if (metricSample.getName().equals(REQUESTS)) {
|
||||
Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 2));
|
||||
}
|
||||
if (metricSample.getName().equals(REQUESTS)) {
|
||||
Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 2));
|
||||
}
|
||||
if (metricSample.getName().equals(PROCESSING)) {
|
||||
Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 0));
|
||||
}
|
||||
if (metricSample.getName().equals(TIMEOUT)) {
|
||||
Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 1));
|
||||
}
|
||||
if (metricSample.getName().equals(TOTAL_FAILED)) {
|
||||
Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 1));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AtomicLong value = (AtomicLong) ((CounterMetricSample<?>) metricSample).getValue();
|
||||
if (metricSample.getName().equals(SUCCEED)) {
|
||||
Assertions.assertEquals(1, value.intValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// calc rt
|
||||
for (MetricSample sample : metricSamples) {
|
||||
Map<String, String> tags = sample.getTags();
|
||||
Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationModel.getApplicationName());
|
||||
}
|
||||
|
||||
Map<String, Long> sampleMap = metricSamples.stream().filter(metricSample -> metricSample instanceof GaugeMetricSample).collect(Collectors.toMap(MetricSample::getName, k -> ((GaugeMetricSample) k).applyAsLong()));
|
||||
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_LAST, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), c2);
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_MIN, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), Math.min(c1, c2));
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_MAX, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), Math.max(c1, c2));
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_AVG, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), (c1 + c2) / 2);
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_SUM, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), c1 + c2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -46,7 +46,10 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_PARAMETER_DESC;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.*;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
|
|
@ -80,7 +83,7 @@ class MetricsFilterTest {
|
|||
filter = new MetricsFilter();
|
||||
|
||||
collector = applicationModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class);
|
||||
if(!initApplication.get()) {
|
||||
if (!initApplication.get()) {
|
||||
collector.collectApplication(applicationModel);
|
||||
initApplication.set(true);
|
||||
}
|
||||
|
|
@ -105,6 +108,8 @@ class MetricsFilterTest {
|
|||
Assertions.assertTrue(metricsMap.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
void testUnknownFailedRequests() {
|
||||
collector.setCollectEnabled(true);
|
||||
|
|
@ -260,14 +265,13 @@ class MetricsFilterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testErrors(){
|
||||
public void testErrors() {
|
||||
testFilterError(RpcException.SERIALIZATION_EXCEPTION, MetricsKey.METRIC_REQUESTS_CODEC_FAILED.formatName(side));
|
||||
testFilterError(RpcException.NETWORK_EXCEPTION, MetricsKey.METRIC_REQUESTS_NETWORK_FAILED.formatName(side));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void testFilterError(int errorCode,MetricsKey metricsKey){
|
||||
private void testFilterError(int errorCode, MetricsKey metricsKey) {
|
||||
setup();
|
||||
collector.setCollectEnabled(true);
|
||||
given(invoker.invoke(invocation)).willThrow(new RpcException(errorCode));
|
||||
|
|
|
|||
|
|
@ -1,209 +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.metrics.collector;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.metrics.TestMetricsInvoker;
|
||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
||||
import org.apache.dubbo.metrics.collector.sample.MethodMetricsSampler;
|
||||
import org.apache.dubbo.metrics.event.MethodEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.RTEvent;
|
||||
import org.apache.dubbo.metrics.listener.MetricsListener;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.*;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
|
||||
|
||||
class DefaultMetricsCollectorTest {
|
||||
|
||||
private FrameworkModel frameworkModel;
|
||||
private ApplicationModel applicationModel;
|
||||
private String interfaceName;
|
||||
private String methodName;
|
||||
private String group;
|
||||
private String version;
|
||||
private RpcInvocation invocation;
|
||||
private String side;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
frameworkModel = FrameworkModel.defaultModel();
|
||||
applicationModel = frameworkModel.newApplication();
|
||||
ApplicationConfig config = new ApplicationConfig();
|
||||
config.setName("MockMetrics");
|
||||
|
||||
applicationModel.getApplicationConfigManager().setApplication(config);
|
||||
|
||||
interfaceName = "org.apache.dubbo.MockInterface";
|
||||
methodName = "mockMethod";
|
||||
group = "mockGroup";
|
||||
version = "1.0.0";
|
||||
|
||||
invocation = new RpcInvocation(methodName, interfaceName, "serviceKey", null, null);
|
||||
invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version);
|
||||
invocation.setAttachment(GROUP_KEY, group);
|
||||
invocation.setAttachment(VERSION_KEY, version);
|
||||
side = CommonConstants.CONSUMER;
|
||||
|
||||
invocation.setInvoker(new TestMetricsInvoker(side));
|
||||
RpcContext.getServiceContext().setUrl(URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&side=" + side));
|
||||
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
applicationModel.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
void testRequestsMetrics() {
|
||||
DefaultMetricsCollector collector = new DefaultMetricsCollector();
|
||||
collector.setCollectEnabled(true);
|
||||
collector.setApplicationName(applicationModel.getApplicationName());
|
||||
|
||||
MethodMetricsSampler methodMetricsCountSampler = collector.getMethodSampler();
|
||||
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.PROCESSING.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.SUCCEED.getNameByType(side));
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side));
|
||||
|
||||
List<MetricSample> samples = collector.collect();
|
||||
for (MetricSample sample : samples) {
|
||||
if(sample instanceof GaugeMetricSample) {
|
||||
GaugeMetricSample gaugeSample = (GaugeMetricSample) sample;
|
||||
Assertions.assertEquals(gaugeSample.applyAsLong(), 1);
|
||||
}else if(sample instanceof CounterMetricSample){
|
||||
CounterMetricSample counterMetricSample = (CounterMetricSample) sample;
|
||||
Assertions.assertEquals(counterMetricSample.getValue().longValue(), 1);
|
||||
}
|
||||
|
||||
Map<String, String> tags = sample.getTags();
|
||||
Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName);
|
||||
Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName);
|
||||
Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group);
|
||||
Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version);
|
||||
|
||||
}
|
||||
|
||||
methodMetricsCountSampler.dec(invocation, MetricsEvent.Type.PROCESSING.getNameByType(side));
|
||||
samples = collector.collect();
|
||||
|
||||
Map<String, Long> sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> {
|
||||
if(k instanceof GaugeMetricSample){
|
||||
return ((GaugeMetricSample) k).applyAsLong();
|
||||
}else if(k instanceof CounterMetricSample){
|
||||
return ((CounterMetricSample)k).getValue().longValue();
|
||||
}else{
|
||||
throw new RuntimeException("un support sample type");
|
||||
}
|
||||
}));
|
||||
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_PROCESSING.getNameByType(side)), 0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRTMetrics() {
|
||||
DefaultMetricsCollector collector = new DefaultMetricsCollector();
|
||||
collector.setCollectEnabled(true);
|
||||
MethodMetricsSampler methodMetricsCountSampler = collector.getMethodSampler();
|
||||
String applicationName = applicationModel.getApplicationName();
|
||||
|
||||
collector.setApplicationName(applicationName);
|
||||
|
||||
methodMetricsCountSampler.addRT(invocation, 10L);
|
||||
methodMetricsCountSampler.addRT(invocation, 0L);
|
||||
|
||||
List<MetricSample> samples = collector.collect();
|
||||
for (MetricSample sample : samples) {
|
||||
Map<String, String> tags = sample.getTags();
|
||||
|
||||
Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName);
|
||||
Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName);
|
||||
Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group);
|
||||
Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<String, Long> sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> ((GaugeMetricSample) k).applyAsLong()));
|
||||
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_LAST.getNameByType(side)), 0L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_MIN.getNameByType(side)), 0L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_MAX.getNameByType(side)), 10L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_AVG.getNameByType(side)), 5L);
|
||||
Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_SUM.getNameByType(side)), 10L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListener() {
|
||||
DefaultMetricsCollector collector = new DefaultMetricsCollector();
|
||||
MethodMetricsSampler methodMetricsCountSampler = collector.getMethodSampler();
|
||||
collector.setCollectEnabled(true);
|
||||
|
||||
MockListener mockListener = new MockListener();
|
||||
collector.addListener(mockListener);
|
||||
collector.setApplicationName(applicationModel.getApplicationName());
|
||||
|
||||
methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL.getNameByType(side));
|
||||
Assertions.assertNotNull(mockListener.getCurEvent());
|
||||
Assertions.assertTrue(mockListener.getCurEvent() instanceof MethodEvent);
|
||||
Assertions.assertEquals(((MethodEvent) mockListener.getCurEvent()).getType(),
|
||||
MetricsEvent.Type.TOTAL.getNameByType(side));
|
||||
|
||||
methodMetricsCountSampler.addRT(invocation, 5L);
|
||||
Assertions.assertTrue(mockListener.getCurEvent() instanceof RTEvent);
|
||||
Assertions.assertEquals(((RTEvent) mockListener.getCurEvent()).getRt(), 5L);
|
||||
}
|
||||
|
||||
static class MockListener implements MetricsListener {
|
||||
|
||||
private MetricsEvent curEvent;
|
||||
|
||||
@Override
|
||||
public void onEvent(MetricsEvent event) {
|
||||
curEvent = event;
|
||||
}
|
||||
|
||||
public MetricsEvent getCurEvent() {
|
||||
return curEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,192 +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.sampler;
|
||||
|
||||
import org.apache.dubbo.metrics.collector.sample.MetricsCountSampleConfigurer;
|
||||
import org.apache.dubbo.metrics.collector.sample.MetricsCountSampler;
|
||||
import org.apache.dubbo.metrics.collector.sample.SimpleMetricsCountSampler;
|
||||
import org.apache.dubbo.metrics.model.Metric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.RT;
|
||||
|
||||
public class CountSamplerTest {
|
||||
String side = "consumer";
|
||||
|
||||
public RequestMetricsCountSampler sampler = new RequestMetricsCountSampler();
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
sampler = new RequestMetricsCountSampler();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rtTest() {
|
||||
String applicationName = "test";
|
||||
|
||||
sampler.addRT(applicationName, RTType.METHOD_REQUEST, 2L);
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<String, GaugeMetricSample> collect = getCollect(RTType.METHOD_REQUEST);
|
||||
|
||||
Assertions.assertNotNull(collect);
|
||||
|
||||
Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_LAST.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_LAST.getNameByType(side)).applyAsLong() == 2);
|
||||
Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_MIN.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_MIN.getNameByType(side)).applyAsLong() == 2);
|
||||
Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_MAX.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_MAX.getNameByType(side)).applyAsLong() == 2);
|
||||
Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_AVG.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_AVG.getNameByType(side)).applyAsLong() == 2);
|
||||
Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_SUM.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_SUM.getNameByType(side)).applyAsLong() == 2);
|
||||
|
||||
sampler.addRT(applicationName, RTType.METHOD_REQUEST, 1L);
|
||||
collect = getCollect(RTType.METHOD_REQUEST);
|
||||
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_LAST.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_LAST.getNameByType(side)).applyAsLong() == 1);
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_MIN.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_MIN.getNameByType(side)).applyAsLong() == 1);
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_MAX.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_MAX.getNameByType(side)).applyAsLong() == 2);
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_AVG.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_AVG.getNameByType(side)).applyAsLong() == 1);
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_SUM.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_SUM.getNameByType(side)).applyAsLong() == 3);
|
||||
|
||||
sampler.addRT(applicationName, RTType.APPLICATION, 4L);
|
||||
collect = getCollect(RTType.APPLICATION);
|
||||
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_LAST.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_LAST.getNameByType(side)).applyAsLong() == 4);
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_MIN.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_MIN.getNameByType(side)).applyAsLong() == 4);
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_MAX.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_MAX.getNameByType(side)).applyAsLong() == 4);
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_AVG.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_AVG.getNameByType(side)).applyAsLong() == 4);
|
||||
Assertions.assertTrue(
|
||||
null != collect.get(MetricsKey.METRIC_RT_SUM.getNameByType(side)) && collect.get(
|
||||
MetricsKey.METRIC_RT_SUM.getNameByType(side)).applyAsLong() == 4);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private Map<String, GaugeMetricSample> getCollect(RTType rtType) {
|
||||
List<GaugeMetricSample<?>> metricSamples = sampler.collectRT(
|
||||
new MetricsCountSampler.MetricSampleFactory<RequestMethodMetrics, GaugeMetricSample<?>>() {
|
||||
@Override
|
||||
public <T> GaugeMetricSample<?> newInstance(MetricsKey key, RequestMethodMetrics metric, T value, ToDoubleFunction<T> apply) {
|
||||
return new GaugeMetricSample<>(key.getNameByType(side), key.getDescription(),
|
||||
metric.getTags(), RT, value, apply);
|
||||
}
|
||||
}, rtType);
|
||||
|
||||
return metricSamples.stream()
|
||||
.collect(Collectors.toMap(MetricSample::getName, v -> v));
|
||||
}
|
||||
|
||||
public class RequestMetricsCountSampler extends SimpleMetricsCountSampler<String, RTType, RequestMethodMetrics> {
|
||||
|
||||
@Override
|
||||
public List<MetricSample> sample() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void countConfigure(
|
||||
MetricsCountSampleConfigurer<String, RTType, RequestMethodMetrics> sampleConfigure) {
|
||||
sampleConfigure.configureMetrics(
|
||||
configure -> new RequestMethodMetrics(configure.getSource()));
|
||||
sampleConfigure.configureEventHandler(configure -> {
|
||||
System.out.println("generic event");
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rtConfigure(
|
||||
MetricsCountSampleConfigurer<String, RTType, RequestMethodMetrics> sampleConfigure) {
|
||||
sampleConfigure.configureMetrics(configure -> new RequestMethodMetrics(configure.getSource()));
|
||||
sampleConfigure.configureEventHandler(configure -> {
|
||||
System.out.println("rt event");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
enum RTType {
|
||||
METHOD_REQUEST,
|
||||
APPLICATION
|
||||
}
|
||||
|
||||
static class RequestMethodMetrics implements Metric {
|
||||
|
||||
private final String applicationName;
|
||||
|
||||
public RequestMethodMetrics(String applicationName) {
|
||||
this.applicationName = applicationName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getTags() {
|
||||
Map<String, String> tags = new HashMap<>();
|
||||
tags.put("serviceName", "test");
|
||||
tags.put("version", "1.0.0");
|
||||
tags.put("uptime", "20220202");
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof RequestMethodMetrics))
|
||||
return false;
|
||||
RequestMethodMetrics that = (RequestMethodMetrics) o;
|
||||
return Objects.equals(applicationName, that.applicationName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(applicationName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,132 +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.sampler;
|
||||
|
||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
||||
import org.apache.dubbo.metrics.collector.sample.MethodMetricsSampler;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.observation.MockInvocation;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class MethodMetricsTest {
|
||||
|
||||
private DefaultMetricsCollector collector;
|
||||
private MethodMetricsSampler sampler;
|
||||
|
||||
private Invocation invocation;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
collector = new DefaultMetricsCollector();
|
||||
sampler = new MethodMetricsSampler(collector);
|
||||
invocation = spy(new MockInvocation());
|
||||
when(invocation.getTargetServiceUniqueName()).thenReturn("TestService-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRequestsCount() {
|
||||
final long requestTimes = 1000L;
|
||||
|
||||
//METRIC_REQUESTS
|
||||
for (long i = 0; i < requestTimes; i++) {
|
||||
sampler.inc(invocation, MetricsEvent.Type.TOTAL.getNameByType("provider"));
|
||||
}
|
||||
|
||||
List<MetricSample> samples = sampler.sample();
|
||||
|
||||
MetricSample requestsSample = samples.stream()
|
||||
.filter(sample -> MetricsKey.METRIC_REQUESTS.getNameByType("provider").equals(sample.getName()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
Assertions.assertNotNull(requestsSample, "METRIC_REQUESTS sample should not be null");
|
||||
Assertions.assertEquals(MetricSample.Type.COUNTER, requestsSample.getType(), "METRIC_REQUESTS sample should have a COUNTER type");
|
||||
Assertions.assertTrue(requestsSample instanceof CounterMetricSample);
|
||||
Assertions.assertEquals(requestTimes, ((CounterMetricSample) requestsSample).getValue().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRequestsProcessing() {
|
||||
final long requestTimes = 1000L;
|
||||
|
||||
//METRIC_REQUESTS
|
||||
for (long i = 0; i < requestTimes; i++) {
|
||||
sampler.inc(invocation, MetricsEvent.Type.PROCESSING.getNameByType("provider"));
|
||||
}
|
||||
|
||||
List<MetricSample> samples = sampler.sample();
|
||||
|
||||
MetricSample requestsSample = samples.stream()
|
||||
.filter(sample -> MetricsKey.METRIC_REQUESTS_PROCESSING.getNameByType("provider").equals(sample.getName()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
Assertions.assertNotNull(requestsSample, "METRIC_REQUESTS_PROCESSING sample should not be null");
|
||||
Assertions.assertEquals(MetricSample.Type.GAUGE, requestsSample.getType(), "METRIC_REQUESTS_PROCESSING sample should have a GAUGE type");
|
||||
Assertions.assertTrue(requestsSample instanceof GaugeMetricSample);
|
||||
Assertions.assertEquals(requestTimes, ((AtomicLong) ((GaugeMetricSample) requestsSample).getValue()).get());
|
||||
|
||||
for (long i = 0; i < requestTimes; i++) {
|
||||
sampler.dec(invocation, MetricsEvent.Type.PROCESSING.getNameByType("provider"));
|
||||
}
|
||||
|
||||
samples = sampler.sample();
|
||||
|
||||
requestsSample = samples.stream()
|
||||
.filter(sample -> MetricsKey.METRIC_REQUESTS_PROCESSING.getNameByType("provider").equals(sample.getName()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
Assertions.assertEquals(0, ((AtomicLong) ((GaugeMetricSample) requestsSample).getValue()).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRequestSucceed() {
|
||||
final long requestTimes = 1000L;
|
||||
|
||||
//METRIC_REQUESTS_SUCCEED
|
||||
for (long i = 0; i < requestTimes; i++) {
|
||||
sampler.inc(invocation, MetricsEvent.Type.SUCCEED.getNameByType("provider"));
|
||||
}
|
||||
|
||||
List<MetricSample> samples = sampler.sample();
|
||||
|
||||
MetricSample requestsSample = samples.stream()
|
||||
.filter(sample -> MetricsKey.METRIC_REQUESTS_SUCCEED.getNameByType("provider").equals(sample.getName()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
Assertions.assertNotNull(requestsSample, "METRIC_REQUESTS_SUCCEED sample should not be null");
|
||||
Assertions.assertEquals(MetricSample.Type.COUNTER, requestsSample.getType(), "METRIC_REQUESTS_SUCCEED sample should have a COUNTER type");
|
||||
Assertions.assertTrue(requestsSample instanceof CounterMetricSample);
|
||||
Assertions.assertEquals(requestTimes, ((AtomicLong) ((CounterMetricSample) requestsSample).getValue()).get());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,8 +18,9 @@
|
|||
package org.apache.dubbo.metrics.metadata;
|
||||
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceType;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
|
@ -36,16 +37,18 @@ import static org.apache.dubbo.metrics.model.key.MetricsKey.STORE_PROVIDER_METAD
|
|||
|
||||
public interface MetadataMetricsConstants {
|
||||
|
||||
MetricsPlaceType OP_TYPE_PUSH = MetricsPlaceType.of("push", MetricsLevel.APP);
|
||||
MetricsPlaceType OP_TYPE_SUBSCRIBE = MetricsPlaceType.of("subscribe", MetricsLevel.APP);
|
||||
MetricsPlaceType OP_TYPE_STORE_PROVIDER_INTERFACE = MetricsPlaceType.of("store.provider.interface", MetricsLevel.SERVICE);
|
||||
MetricsPlaceValue OP_TYPE_PUSH = MetricsPlaceValue.of("push", MetricsLevel.APP);
|
||||
MetricsPlaceValue OP_TYPE_SUBSCRIBE = MetricsPlaceValue.of("subscribe", MetricsLevel.APP);
|
||||
MetricsPlaceValue OP_TYPE_STORE_PROVIDER_INTERFACE = MetricsPlaceValue.of("store.provider.interface", MetricsLevel.SERVICE);
|
||||
|
||||
// App-level
|
||||
List<MetricsKey> APP_LEVEL_KEYS = Arrays.asList(METADATA_PUSH_METRIC_NUM, METADATA_PUSH_METRIC_NUM_SUCCEED, METADATA_PUSH_METRIC_NUM_FAILED,
|
||||
METADATA_SUBSCRIBE_METRIC_NUM, METADATA_SUBSCRIBE_METRIC_NUM_SUCCEED, METADATA_SUBSCRIBE_METRIC_NUM_FAILED);
|
||||
|
||||
// Service-level
|
||||
List<MetricsKey> SERVICE_LEVEL_KEYS = Arrays.asList(STORE_PROVIDER_METADATA,
|
||||
STORE_PROVIDER_METADATA_SUCCEED, STORE_PROVIDER_METADATA_FAILED
|
||||
List<MetricsKeyWrapper> SERVICE_LEVEL_KEYS = Arrays.asList(
|
||||
new MetricsKeyWrapper(STORE_PROVIDER_METADATA, OP_TYPE_STORE_PROVIDER_INTERFACE),
|
||||
new MetricsKeyWrapper(STORE_PROVIDER_METADATA_SUCCEED, OP_TYPE_STORE_PROVIDER_INTERFACE),
|
||||
new MetricsKeyWrapper(STORE_PROVIDER_METADATA_FAILED, OP_TYPE_STORE_PROVIDER_INTERFACE)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,9 @@ import org.apache.dubbo.metrics.data.ApplicationStatComposite;
|
|||
import org.apache.dubbo.metrics.data.BaseStatComposite;
|
||||
import org.apache.dubbo.metrics.data.RtStatComposite;
|
||||
import org.apache.dubbo.metrics.data.ServiceStatComposite;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.metadata.MetadataMetricsConstants;
|
||||
import org.apache.dubbo.metrics.metadata.event.MetadataEvent;
|
||||
import org.apache.dubbo.metrics.metadata.event.MetadataMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.metadata.event.MetadataSubDispatcher;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
|
@ -47,7 +45,7 @@ import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE
|
|||
* Registry implementation of {@link MetricsCollector}
|
||||
*/
|
||||
@Activate
|
||||
public class MetadataMetricsCollector extends CombMetricsCollector<TimeCounterEvent> {
|
||||
public class MetadataMetricsCollector extends CombMetricsCollector<MetadataEvent> {
|
||||
|
||||
private Boolean collectEnabled = null;
|
||||
private final ApplicationModel applicationModel;
|
||||
|
|
@ -55,13 +53,21 @@ public class MetadataMetricsCollector extends CombMetricsCollector<TimeCounterEv
|
|||
public MetadataMetricsCollector(ApplicationModel applicationModel) {
|
||||
super(new BaseStatComposite() {
|
||||
@Override
|
||||
protected void init(ApplicationStatComposite applicationStatComposite, ServiceStatComposite serviceStatComposite, RtStatComposite rtStatComposite) {
|
||||
protected void init(ApplicationStatComposite applicationStatComposite) {
|
||||
applicationStatComposite.init(MetadataMetricsConstants.APP_LEVEL_KEYS);
|
||||
serviceStatComposite.init(MetadataMetricsConstants.SERVICE_LEVEL_KEYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(ServiceStatComposite serviceStatComposite) {
|
||||
serviceStatComposite.initWrapper(MetadataMetricsConstants.SERVICE_LEVEL_KEYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(RtStatComposite rtStatComposite) {
|
||||
rtStatComposite.init(OP_TYPE_PUSH, OP_TYPE_SUBSCRIBE, OP_TYPE_STORE_PROVIDER_INTERFACE);
|
||||
}
|
||||
});
|
||||
super.setEventMulticaster(new MetadataMetricsEventMulticaster(this));
|
||||
super.setEventMulticaster(new MetadataSubDispatcher(this));
|
||||
this.applicationModel = applicationModel;
|
||||
}
|
||||
|
||||
|
|
@ -90,9 +96,4 @@ public class MetadataMetricsCollector extends CombMetricsCollector<TimeCounterEv
|
|||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof MetadataEvent;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ import static org.apache.dubbo.metrics.model.key.MetricsKey.STORE_PROVIDER_METAD
|
|||
*/
|
||||
public class MetadataEvent extends TimeCounterEvent {
|
||||
public MetadataEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
|
||||
super(applicationModel);
|
||||
super.typeWrapper = typeWrapper;
|
||||
super(applicationModel,typeWrapper);
|
||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||
MetadataMetricsCollector collector;
|
||||
if (!beanFactory.isDestroyed()) {
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE
|
|||
import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE_STORE_PROVIDER_INTERFACE;
|
||||
import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE_SUBSCRIBE;
|
||||
|
||||
public final class MetadataMetricsEventMulticaster extends SimpleMetricsEventMulticaster {
|
||||
public final class MetadataSubDispatcher extends SimpleMetricsEventMulticaster {
|
||||
|
||||
public MetadataMetricsEventMulticaster(MetadataMetricsCollector collector) {
|
||||
public MetadataSubDispatcher(MetadataMetricsCollector collector) {
|
||||
|
||||
CategorySet.ALL.forEach(categorySet ->
|
||||
{
|
||||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.metrics.metadata;
|
|||
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.metadata.collector.MetadataMetricsCollector;
|
||||
import org.apache.dubbo.metrics.metadata.event.MetadataEvent;
|
||||
|
|
@ -41,7 +42,9 @@ import java.util.Objects;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
|
||||
import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.*;
|
||||
import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE_PUSH;
|
||||
import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE_STORE_PROVIDER_INTERFACE;
|
||||
import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE_SUBSCRIBE;
|
||||
|
||||
|
||||
class MetadataMetricsCollectorTest {
|
||||
|
|
@ -64,6 +67,16 @@ class MetadataMetricsCollectorTest {
|
|||
collector.setCollectEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListener() {
|
||||
MetadataEvent event = MetadataEvent.toPushEvent(applicationModel);
|
||||
MetricsEvent otherEvent = new MetricsEvent(applicationModel,null){
|
||||
};
|
||||
Assertions.assertTrue(collector.isSupport(event));
|
||||
Assertions.assertFalse(collector.isSupport(otherEvent));
|
||||
}
|
||||
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
applicationModel.destroy();
|
||||
|
|
|
|||
|
|
@ -40,10 +40,17 @@ public class MetadataStatCompositeTest {
|
|||
|
||||
private final BaseStatComposite statComposite = new BaseStatComposite() {
|
||||
@Override
|
||||
protected void init(ApplicationStatComposite applicationStatComposite, ServiceStatComposite
|
||||
serviceStatComposite, RtStatComposite rtStatComposite) {
|
||||
protected void init(ApplicationStatComposite applicationStatComposite) {
|
||||
applicationStatComposite.init(MetadataMetricsConstants.APP_LEVEL_KEYS);
|
||||
serviceStatComposite.init(MetadataMetricsConstants.SERVICE_LEVEL_KEYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(ServiceStatComposite serviceStatComposite) {
|
||||
serviceStatComposite.initWrapper(MetadataMetricsConstants.SERVICE_LEVEL_KEYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(RtStatComposite rtStatComposite) {
|
||||
rtStatComposite.init(OP_TYPE_PUSH, OP_TYPE_SUBSCRIBE, OP_TYPE_STORE_PROVIDER_INTERFACE);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@
|
|||
package org.apache.dubbo.metrics.registry;
|
||||
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceType;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
|
@ -45,12 +46,12 @@ import static org.apache.dubbo.metrics.model.key.MetricsKey.SUBSCRIBE_METRIC_NUM
|
|||
|
||||
public interface RegistryMetricsConstants {
|
||||
|
||||
MetricsPlaceType OP_TYPE_REGISTER = MetricsPlaceType.of("register", MetricsLevel.APP);
|
||||
MetricsPlaceType OP_TYPE_SUBSCRIBE = MetricsPlaceType.of("subscribe", MetricsLevel.APP);
|
||||
MetricsPlaceType OP_TYPE_NOTIFY = MetricsPlaceType.of("notify", MetricsLevel.APP);
|
||||
MetricsPlaceType OP_TYPE_DIRECTORY = MetricsPlaceType.of("directory", MetricsLevel.APP);
|
||||
MetricsPlaceType OP_TYPE_REGISTER_SERVICE = MetricsPlaceType.of("register.service", MetricsLevel.SERVICE);
|
||||
MetricsPlaceType OP_TYPE_SUBSCRIBE_SERVICE = MetricsPlaceType.of("subscribe.service", MetricsLevel.SERVICE);
|
||||
MetricsPlaceValue OP_TYPE_REGISTER = MetricsPlaceValue.of("register", MetricsLevel.APP);
|
||||
MetricsPlaceValue OP_TYPE_SUBSCRIBE = MetricsPlaceValue.of("subscribe", MetricsLevel.APP);
|
||||
MetricsPlaceValue OP_TYPE_NOTIFY = MetricsPlaceValue.of("notify", MetricsLevel.APP);
|
||||
MetricsPlaceValue OP_TYPE_DIRECTORY = MetricsPlaceValue.of("directory", MetricsLevel.APP);
|
||||
MetricsPlaceValue OP_TYPE_REGISTER_SERVICE = MetricsPlaceValue.of("register.service", MetricsLevel.SERVICE);
|
||||
MetricsPlaceValue OP_TYPE_SUBSCRIBE_SERVICE = MetricsPlaceValue.of("subscribe.service", MetricsLevel.SERVICE);
|
||||
|
||||
// App-level
|
||||
List<MetricsKey> APP_LEVEL_KEYS = Arrays.asList(REGISTER_METRIC_REQUESTS, REGISTER_METRIC_REQUESTS_SUCCEED, REGISTER_METRIC_REQUESTS_FAILED,
|
||||
|
|
@ -58,11 +59,17 @@ public interface RegistryMetricsConstants {
|
|||
NOTIFY_METRIC_REQUESTS);
|
||||
|
||||
// Service-level
|
||||
List<MetricsKey> SERVICE_LEVEL_KEYS = Arrays.asList(NOTIFY_METRIC_NUM_LAST,
|
||||
SERVICE_REGISTER_METRIC_REQUESTS, SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, SERVICE_REGISTER_METRIC_REQUESTS_FAILED,
|
||||
SERVICE_SUBSCRIBE_METRIC_NUM, SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, SERVICE_SUBSCRIBE_METRIC_NUM_FAILED,
|
||||
DIRECTORY_METRIC_NUM_VALID, DIRECTORY_METRIC_NUM_TO_RECONNECT, DIRECTORY_METRIC_NUM_DISABLE, DIRECTORY_METRIC_NUM_ALL
|
||||
List<MetricsKeyWrapper> SERVICE_LEVEL_KEYS = Arrays.asList(
|
||||
new MetricsKeyWrapper(NOTIFY_METRIC_NUM_LAST, OP_TYPE_NOTIFY),
|
||||
new MetricsKeyWrapper(SERVICE_REGISTER_METRIC_REQUESTS, OP_TYPE_REGISTER_SERVICE),
|
||||
new MetricsKeyWrapper(SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, OP_TYPE_REGISTER_SERVICE),
|
||||
new MetricsKeyWrapper(SERVICE_REGISTER_METRIC_REQUESTS_FAILED, OP_TYPE_REGISTER_SERVICE),
|
||||
new MetricsKeyWrapper(SERVICE_SUBSCRIBE_METRIC_NUM, OP_TYPE_SUBSCRIBE_SERVICE),
|
||||
new MetricsKeyWrapper(SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, OP_TYPE_SUBSCRIBE_SERVICE),
|
||||
new MetricsKeyWrapper(SERVICE_SUBSCRIBE_METRIC_NUM_FAILED, OP_TYPE_SUBSCRIBE_SERVICE),
|
||||
new MetricsKeyWrapper(DIRECTORY_METRIC_NUM_VALID, OP_TYPE_DIRECTORY),
|
||||
new MetricsKeyWrapper(DIRECTORY_METRIC_NUM_TO_RECONNECT, OP_TYPE_DIRECTORY),
|
||||
new MetricsKeyWrapper(DIRECTORY_METRIC_NUM_DISABLE, OP_TYPE_DIRECTORY),
|
||||
new MetricsKeyWrapper(DIRECTORY_METRIC_NUM_ALL, OP_TYPE_DIRECTORY)
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,11 @@ import org.apache.dubbo.metrics.data.ApplicationStatComposite;
|
|||
import org.apache.dubbo.metrics.data.BaseStatComposite;
|
||||
import org.apache.dubbo.metrics.data.RtStatComposite;
|
||||
import org.apache.dubbo.metrics.data.ServiceStatComposite;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistrySubDispatcher;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -49,7 +47,7 @@ import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE
|
|||
* Registry implementation of {@link MetricsCollector}
|
||||
*/
|
||||
@Activate
|
||||
public class RegistryMetricsCollector extends CombMetricsCollector<TimeCounterEvent> {
|
||||
public class RegistryMetricsCollector extends CombMetricsCollector<RegistryEvent> {
|
||||
|
||||
private Boolean collectEnabled = null;
|
||||
private final ApplicationModel applicationModel;
|
||||
|
|
@ -57,13 +55,21 @@ public class RegistryMetricsCollector extends CombMetricsCollector<TimeCounterEv
|
|||
public RegistryMetricsCollector(ApplicationModel applicationModel) {
|
||||
super(new BaseStatComposite() {
|
||||
@Override
|
||||
protected void init(ApplicationStatComposite applicationStatComposite, ServiceStatComposite serviceStatComposite, RtStatComposite rtStatComposite) {
|
||||
protected void init(ApplicationStatComposite applicationStatComposite) {
|
||||
applicationStatComposite.init(RegistryMetricsConstants.APP_LEVEL_KEYS);
|
||||
serviceStatComposite.init(RegistryMetricsConstants.SERVICE_LEVEL_KEYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(ServiceStatComposite serviceStatComposite) {
|
||||
serviceStatComposite.initWrapper(RegistryMetricsConstants.SERVICE_LEVEL_KEYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(RtStatComposite rtStatComposite) {
|
||||
rtStatComposite.init(OP_TYPE_REGISTER, OP_TYPE_SUBSCRIBE, OP_TYPE_NOTIFY, OP_TYPE_REGISTER_SERVICE, OP_TYPE_SUBSCRIBE_SERVICE);
|
||||
}
|
||||
});
|
||||
super.setEventMulticaster(new RegistryMetricsEventMulticaster(this));
|
||||
super.setEventMulticaster(new RegistrySubDispatcher(this));
|
||||
this.applicationModel = applicationModel;
|
||||
}
|
||||
|
||||
|
|
@ -93,10 +99,4 @@ public class RegistryMetricsCollector extends CombMetricsCollector<TimeCounterEv
|
|||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RegistryEvent;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,8 +38,7 @@ import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SIZE;
|
|||
*/
|
||||
public class RegistryEvent extends TimeCounterEvent {
|
||||
public RegistryEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
|
||||
super(applicationModel);
|
||||
super.typeWrapper = typeWrapper;
|
||||
super(applicationModel,typeWrapper);
|
||||
ScopeBeanFactory beanFactory = getSource().getBeanFactory();
|
||||
RegistryMetricsCollector collector;
|
||||
if (!beanFactory.isDestroyed()) {
|
||||
|
|
@ -59,7 +58,7 @@ public class RegistryEvent extends TimeCounterEvent {
|
|||
|
||||
|
||||
public static RegistryEvent toNotifyEvent(ApplicationModel applicationModel) {
|
||||
return new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsKey.NOTIFY_METRIC_NUM_LAST, null)) {
|
||||
return new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsKey.NOTIFY_METRIC_NUM_LAST, (MetricsKey) null)) {
|
||||
@Override
|
||||
public void customAfterPost(Object postResult) {
|
||||
super.putAttachment(ATTACHMENT_KEY_LAST_NUM_MAP, postResult);
|
||||
|
|
|
|||
|
|
@ -18,12 +18,13 @@
|
|||
package org.apache.dubbo.metrics.registry.event;
|
||||
|
||||
import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsListener;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener;
|
||||
import org.apache.dubbo.metrics.listener.MetricsApplicationListener;
|
||||
import org.apache.dubbo.metrics.listener.MetricsServiceListener;
|
||||
import org.apache.dubbo.metrics.model.key.CategoryOverall;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsCat;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
|
@ -40,10 +41,10 @@ import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE
|
|||
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_SUBSCRIBE;
|
||||
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_SUBSCRIBE_SERVICE;
|
||||
|
||||
public final class RegistryMetricsEventMulticaster extends SimpleMetricsEventMulticaster {
|
||||
public final class RegistrySubDispatcher extends SimpleMetricsEventMulticaster {
|
||||
|
||||
|
||||
public RegistryMetricsEventMulticaster(RegistryMetricsCollector collector) {
|
||||
public RegistrySubDispatcher(RegistryMetricsCollector collector) {
|
||||
|
||||
CategorySet.ALL.forEach(categorySet ->
|
||||
{
|
||||
|
|
@ -83,24 +84,24 @@ public final class RegistryMetricsEventMulticaster extends SimpleMetricsEventMul
|
|||
// MetricsNotifyListener
|
||||
MetricsCat APPLICATION_NOTIFY_POST = new MetricsCat(MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsApplicationListener::onPostEventBuild);
|
||||
MetricsCat APPLICATION_NOTIFY_FINISH = new MetricsCat(MetricsKey.NOTIFY_METRIC_NUM_LAST,
|
||||
(key, placeType, collector) -> AbstractMetricsListener.onFinish(key,
|
||||
(key, placeType, collector) -> AbstractMetricsKeyListener.onFinish(key,
|
||||
event -> {
|
||||
collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc());
|
||||
Map<String, Integer> lastNumMap = Collections.unmodifiableMap(event.getAttachmentValue(ATTACHMENT_KEY_LAST_NUM_MAP));
|
||||
lastNumMap.forEach(
|
||||
(k, v) -> collector.setNum(key, event.appName(), k, v));
|
||||
(k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_NOTIFY), event.appName(), k, v));
|
||||
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
MetricsCat APPLICATION_DIRECTORY_POST = new MetricsCat(MetricsKey.DIRECTORY_METRIC_NUM_VALID, (key, placeType, collector) -> AbstractMetricsListener.onEvent(key,
|
||||
MetricsCat APPLICATION_DIRECTORY_POST = new MetricsCat(MetricsKey.DIRECTORY_METRIC_NUM_VALID, (key, placeType, collector) -> AbstractMetricsKeyListener.onEvent(key,
|
||||
event ->
|
||||
{
|
||||
Map<MetricsKey, Map<String, Integer>> summaryMap = event.getAttachmentValue(ATTACHMENT_DIRECTORY_MAP);
|
||||
summaryMap.forEach((metricsKey, map) ->
|
||||
map.forEach(
|
||||
(k, v) -> collector.setNum(metricsKey, event.appName(), k, v)));
|
||||
(k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_DIRECTORY), event.appName(), k, v)));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
@ -20,9 +20,9 @@ package org.apache.dubbo.metrics.registry.metrics.collector;
|
|||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.TimePair;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
|
||||
|
|
@ -34,6 +34,7 @@ import org.junit.jupiter.api.Assertions;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
|
@ -48,6 +49,7 @@ import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE
|
|||
class RegistryMetricsCollectorTest {
|
||||
|
||||
private ApplicationModel applicationModel;
|
||||
private RegistryMetricsCollector collector;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
|
|
@ -57,7 +59,9 @@ class RegistryMetricsCollectorTest {
|
|||
config.setName("MockMetrics");
|
||||
|
||||
applicationModel.getApplicationConfigManager().setApplication(config);
|
||||
|
||||
applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class);
|
||||
collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class);
|
||||
collector.setCollectEnabled(true);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
|
@ -68,10 +72,6 @@ class RegistryMetricsCollectorTest {
|
|||
@Test
|
||||
void testRegisterMetrics() {
|
||||
|
||||
applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class);
|
||||
RegistryMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class);
|
||||
collector.setCollectEnabled(true);
|
||||
|
||||
RegistryEvent registryEvent = RegistryEvent.toRegisterEvent(applicationModel);
|
||||
MetricsEventBus.post(registryEvent,
|
||||
() -> {
|
||||
|
|
@ -130,9 +130,6 @@ class RegistryMetricsCollectorTest {
|
|||
@Test
|
||||
void testServicePushMetrics() {
|
||||
|
||||
applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class);
|
||||
RegistryMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class);
|
||||
collector.setCollectEnabled(true);
|
||||
String serviceName = "demo.gameService";
|
||||
|
||||
RegistryEvent registryEvent = RegistryEvent.toRsEvent(applicationModel, serviceName, 2);
|
||||
|
|
@ -195,9 +192,6 @@ class RegistryMetricsCollectorTest {
|
|||
@Test
|
||||
void testServiceSubscribeMetrics() {
|
||||
|
||||
applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class);
|
||||
RegistryMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class);
|
||||
collector.setCollectEnabled(true);
|
||||
String serviceName = "demo.gameService";
|
||||
|
||||
RegistryEvent subscribeEvent = RegistryEvent.toSsEvent(applicationModel, serviceName);
|
||||
|
|
@ -255,4 +249,28 @@ class RegistryMetricsCollectorTest {
|
|||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_AVG, OP_TYPE_SUBSCRIBE_SERVICE).targetKey()), (c1 + c2) / 2);
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_SUM, OP_TYPE_SUBSCRIBE_SERVICE).targetKey()), c1 + c2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNotify() {
|
||||
MetricsEventBus.post(RegistryEvent.toNotifyEvent(applicationModel),
|
||||
() -> {
|
||||
try {
|
||||
Thread.sleep(50L);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Map<String, Integer> lastNumMap = new HashMap<>();
|
||||
// 1 different services
|
||||
lastNumMap.put("demo.service1", 3);
|
||||
lastNumMap.put("demo.service2", 4);
|
||||
lastNumMap.put("demo.service3", 5);
|
||||
return lastNumMap;
|
||||
}
|
||||
);
|
||||
List<MetricSample> metricSamples = collector.collect();
|
||||
// num(total+service*3) + rt(5) = 9
|
||||
Assertions.assertEquals(9, metricSamples.size());
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ import org.apache.dubbo.metrics.data.RtStatComposite;
|
|||
import org.apache.dubbo.metrics.data.ServiceStatComposite;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.container.LongContainer;
|
||||
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
|
@ -50,9 +50,17 @@ public class RegistryStatCompositeTest {
|
|||
private final String applicationName = "app1";
|
||||
private final BaseStatComposite statComposite = new BaseStatComposite() {
|
||||
@Override
|
||||
protected void init(ApplicationStatComposite applicationStatComposite, ServiceStatComposite serviceStatComposite, RtStatComposite rtStatComposite) {
|
||||
protected void init(ApplicationStatComposite applicationStatComposite) {
|
||||
applicationStatComposite.init(RegistryMetricsConstants.APP_LEVEL_KEYS);
|
||||
serviceStatComposite.init(RegistryMetricsConstants.SERVICE_LEVEL_KEYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(ServiceStatComposite serviceStatComposite) {
|
||||
serviceStatComposite.initWrapper(RegistryMetricsConstants.SERVICE_LEVEL_KEYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(RtStatComposite rtStatComposite) {
|
||||
rtStatComposite.init(OP_TYPE_REGISTER, OP_TYPE_SUBSCRIBE, OP_TYPE_NOTIFY, OP_TYPE_REGISTER_SERVICE, OP_TYPE_SUBSCRIBE_SERVICE);
|
||||
}
|
||||
};
|
||||
|
|
@ -63,7 +71,7 @@ public class RegistryStatCompositeTest {
|
|||
//(rt)5 * (applicationRegister,subscribe,notify,applicationRegister.service,subscribe.service)
|
||||
Assertions.assertEquals(5 * 5, statComposite.getRtStatComposite().getRtStats().size());
|
||||
statComposite.getApplicationStatComposite().getApplicationNumStats().values().forEach((v ->
|
||||
Assertions.assertEquals(v, new ConcurrentHashMap<>())));
|
||||
Assertions.assertEquals(v, new ConcurrentHashMap<>())));
|
||||
statComposite.getRtStatComposite().getRtStats().forEach(rtContainer ->
|
||||
{
|
||||
for (Map.Entry<String, ? extends Number> entry : rtContainer.entrySet()) {
|
||||
|
|
@ -98,20 +106,20 @@ public class RegistryStatCompositeTest {
|
|||
statComposite.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime1);
|
||||
statComposite.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime2);
|
||||
|
||||
List<GaugeMetricSample> exportedRtMetrics = statComposite.export(MetricsCategory.RT);
|
||||
List<MetricSample> exportedRtMetrics = statComposite.export(MetricsCategory.RT);
|
||||
|
||||
GaugeMetricSample minSample = exportedRtMetrics.stream()
|
||||
.filter(sample -> sample.getTags().containsValue(applicationName))
|
||||
.filter(sample -> sample.getName().equals(METRIC_RT_MIN.getNameByType("register.service")))
|
||||
.findFirst().orElse(null);
|
||||
GaugeMetricSample maxSample = exportedRtMetrics.stream()
|
||||
.filter(sample -> sample.getTags().containsValue(applicationName))
|
||||
.filter(sample -> sample.getName().equals(METRIC_RT_MAX.getNameByType("register.service")))
|
||||
.findFirst().orElse(null);
|
||||
GaugeMetricSample avgSample = exportedRtMetrics.stream()
|
||||
.filter(sample -> sample.getTags().containsValue(applicationName))
|
||||
.filter(sample -> sample.getName().equals(METRIC_RT_AVG.getNameByType("register.service")))
|
||||
.findFirst().orElse(null);
|
||||
GaugeMetricSample minSample = (GaugeMetricSample) exportedRtMetrics.stream()
|
||||
.filter(sample -> sample.getTags().containsValue(applicationName))
|
||||
.filter(sample -> sample.getName().equals(METRIC_RT_MIN.getNameByType("register.service")))
|
||||
.findFirst().orElse(null);
|
||||
GaugeMetricSample maxSample = (GaugeMetricSample) exportedRtMetrics.stream()
|
||||
.filter(sample -> sample.getTags().containsValue(applicationName))
|
||||
.filter(sample -> sample.getName().equals(METRIC_RT_MAX.getNameByType("register.service")))
|
||||
.findFirst().orElse(null);
|
||||
GaugeMetricSample avgSample = (GaugeMetricSample) exportedRtMetrics.stream()
|
||||
.filter(sample -> sample.getTags().containsValue(applicationName))
|
||||
.filter(sample -> sample.getName().equals(METRIC_RT_AVG.getNameByType("register.service")))
|
||||
.findFirst().orElse(null);
|
||||
|
||||
Assertions.assertNotNull(minSample);
|
||||
Assertions.assertNotNull(maxSample);
|
||||
|
|
|
|||
Loading…
Reference in New Issue