diff --git a/dubbo-cluster/pom.xml b/dubbo-cluster/pom.xml
index f7235cf7d6..744d0f9f11 100644
--- a/dubbo-cluster/pom.xml
+++ b/dubbo-cluster/pom.xml
@@ -68,5 +68,11 @@
${project.parent.version}
test
+
+ org.apache.dubbo
+ dubbo-metrics-registry
+ ${project.parent.version}
+ compile
+
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java
index eb69309f24..6af8bdb98d 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java
@@ -16,6 +16,31 @@
*/
package org.apache.dubbo.rpc.cluster.directory;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.config.Configuration;
+import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.constants.LoggerCodeConstants;
+import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
+import org.apache.dubbo.common.utils.ConcurrentHashSet;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
+import org.apache.dubbo.metrics.registry.event.RegistryEvent;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.RouterChain;
+import org.apache.dubbo.rpc.cluster.SingleRouterChain;
+import org.apache.dubbo.rpc.cluster.router.state.BitList;
+import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -31,29 +56,6 @@ import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.Version;
-import org.apache.dubbo.common.config.Configuration;
-import org.apache.dubbo.common.config.ConfigurationUtils;
-import org.apache.dubbo.common.constants.LoggerCodeConstants;
-import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
-import org.apache.dubbo.common.utils.ConcurrentHashSet;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.Router;
-import org.apache.dubbo.rpc.cluster.RouterChain;
-import org.apache.dubbo.rpc.cluster.SingleRouterChain;
-import org.apache.dubbo.rpc.cluster.router.state.BitList;
-import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RECONNECT_TASK_PERIOD;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RECONNECT_TASK_TRY_COUNT;
@@ -128,6 +130,10 @@ public abstract class AbstractDirectory implements Directory {
*/
private final int reconnectTaskPeriod;
+ private final GlobalMetricsEventMulticaster eventMulticaster;
+
+ private ApplicationModel applicationModel;
+
public AbstractDirectory(URL url) {
this(url, null, false);
}
@@ -153,7 +159,7 @@ public abstract class AbstractDirectory implements Directory {
}
// remove some local only parameters
- ApplicationModel applicationModel = url.getOrDefaultApplicationModel();
+ applicationModel = url.getOrDefaultApplicationModel();
this.queryMap = applicationModel.getBeanFactory().getBean(ClusterUtils.class).mergeLocalParams(queryMap);
if (consumerUrl == null) {
@@ -179,12 +185,14 @@ public abstract class AbstractDirectory implements Directory {
this.reconnectTaskTryCount = configuration.getInt(RECONNECT_TASK_TRY_COUNT, DEFAULT_RECONNECT_TASK_TRY_COUNT);
this.reconnectTaskPeriod = configuration.getInt(RECONNECT_TASK_PERIOD, DEFAULT_RECONNECT_TASK_PERIOD);
setRouterChain(routerChain);
+
+ eventMulticaster = applicationModel.getBeanFactory().getBean(GlobalMetricsEventMulticaster.class);
}
@Override
public List> list(Invocation invocation) throws RpcException {
if (destroyed) {
- throw new RpcException("Directory of type " + this.getClass().getSimpleName() + " already destroyed for service " + getConsumerUrl().getServiceKey() + " from registry " + getUrl());
+ throw new RpcException("Directory of type " + this.getClass().getSimpleName() + " already destroyed for service " + getConsumerUrl().getServiceKey() + " from registry " + getUrl());
}
BitList> availableInvokers;
@@ -381,6 +389,7 @@ public abstract class AbstractDirectory implements Directory {
@Override
public void addDisabledInvoker(Invoker invoker) {
+ eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_DISABLE));
if (invokers.contains(invoker)) {
disabledInvokers.add(invoker);
removeValidInvoker(invoker);
@@ -390,6 +399,7 @@ public abstract class AbstractDirectory implements Directory {
@Override
public void recoverDisabledInvoker(Invoker invoker) {
+ eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_RECOVER_DISABLE));
if (disabledInvokers.remove(invoker)) {
try {
addValidInvoker(invoker);
@@ -453,6 +463,7 @@ public abstract class AbstractDirectory implements Directory {
this.invokers = invokers;
refreshInvokerInternal();
this.invokersInitialized = true;
+ eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_CURRENT, invokers.size()));
}
protected void destroyInvokers() {
@@ -463,12 +474,14 @@ public abstract class AbstractDirectory implements Directory {
}
private boolean addValidInvoker(Invoker invoker) {
+ eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_VALID));
synchronized (this.validInvokers) {
return this.validInvokers.add(invoker);
}
}
private boolean removeValidInvoker(Invoker invoker) {
+ eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_UN_VALID));
synchronized (this.validInvokers) {
return this.validInvokers.remove(invoker);
}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectoryTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectoryTest.java
index 379d50b1c1..62787ccd2b 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectoryTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectoryTest.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.cluster.directory;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.Holder;
import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.cluster.router.MockInvoker;
@@ -26,6 +27,7 @@ import org.apache.dubbo.rpc.cluster.router.condition.ConditionStateRouterFactory
import org.apache.dubbo.rpc.cluster.router.state.BitList;
import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -60,6 +62,7 @@ class StaticDirectoryTest {
List> filteredInvokers = router.route(invokers.clone(), URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), new RpcInvocation(), false, new Holder<>());
+ ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
StaticDirectory staticDirectory = new StaticDirectory<>(filteredInvokers);
boolean isAvailable = staticDirectory.isAvailable();
Assertions.assertTrue(!isAvailable);
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java
index 665a9ef65d..9028114aab 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java
@@ -16,18 +16,11 @@
*/
package org.apache.dubbo.rpc.cluster.support;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
@@ -41,6 +34,7 @@ import org.apache.dubbo.rpc.cluster.filter.DemoService;
import org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance;
import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
import org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@@ -50,6 +44,14 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
import static org.apache.dubbo.common.constants.CommonConstants.ENABLE_CONNECTIVITY_VALIDATION;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
@@ -104,6 +106,7 @@ class AbstractClusterInvokerTest {
@SuppressWarnings({"unchecked"})
@BeforeEach
public void setUp() throws Exception {
+ ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
Map attributes = new HashMap<>();
attributes.put("application", "abstractClusterInvokerTest");
url = url.putAttribute(REFER_KEY, attributes);
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ConnectivityValidationTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ConnectivityValidationTest.java
index 0ccb77b8d5..59fc9cfd10 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ConnectivityValidationTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ConnectivityValidationTest.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.cluster.support;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
@@ -28,6 +29,7 @@ import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.LoadBalance;
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@@ -70,6 +72,7 @@ class ConnectivityValidationTest {
@BeforeEach
public void setup() {
+ ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
invoker1 = Mockito.mock(Invoker.class);
invoker2 = Mockito.mock(Invoker.class);
invoker3 = Mockito.mock(Invoker.class);
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
index 736d5a71d2..de20e2d262 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
@@ -16,11 +16,8 @@
*/
package org.apache.dubbo.rpc.cluster.support;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
@@ -33,10 +30,15 @@ import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.SingleRouterChain;
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
import org.apache.dubbo.rpc.cluster.router.state.BitList;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.protocol.AbstractInvoker;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertSame;
@@ -65,7 +67,7 @@ class FailoverClusterInvokerTest {
@BeforeEach
public void setUp() throws Exception {
-
+ ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
dic = mock(Directory.class);
given(dic.getUrl()).willReturn(url);
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java
index 62646cb201..7db7129e81 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.rpc.cluster.support.wrapper;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
@@ -28,6 +29,7 @@ import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.cluster.LoadBalance;
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.support.MockProtocol;
import org.junit.jupiter.api.Assertions;
@@ -49,6 +51,7 @@ class MockClusterInvokerTest {
@BeforeEach
public void beforeMethod() {
+ ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
invokers.clear();
}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockProviderRpcExceptionTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockProviderRpcExceptionTest.java
index 89917f1de9..c0a737280f 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockProviderRpcExceptionTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockProviderRpcExceptionTest.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.rpc.cluster.support.wrapper;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.ProxyFactory;
@@ -28,6 +29,7 @@ import org.apache.dubbo.rpc.cluster.LoadBalance;
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -46,6 +48,7 @@ class MockProviderRpcExceptionTest {
@BeforeEach
public void beforeMethod() {
+ ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
invokers.clear();
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java
index 1b8340138b..07a1e5f425 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java
@@ -41,7 +41,12 @@ public class MetricsConfig extends AbstractConfig {
private Boolean enableJvmMetrics;
/**
- * Enable jvm metrics when collecting.
+ * Enable registry metrics.
+ */
+ private Boolean enableRegistryMetrics;
+
+ /**
+ * Enable metadata metrics.
*/
private Boolean enableMetadataMetrics;
@@ -103,6 +108,14 @@ public class MetricsConfig extends AbstractConfig {
this.enableJvmMetrics = enableJvmMetrics;
}
+ public Boolean getEnableRegistryMetrics() {
+ return enableRegistryMetrics;
+ }
+
+ public void setEnableRegistryMetrics(Boolean enableRegistryMetrics) {
+ this.enableRegistryMetrics = enableRegistryMetrics;
+ }
+
public String getPort() {
return port;
}
diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml
index 2ba42d26a3..42ee10a4e0 100644
--- a/dubbo-config/dubbo-config-api/pom.xml
+++ b/dubbo-config/dubbo-config-api/pom.xml
@@ -42,12 +42,24 @@
${project.parent.version}
+
+ org.apache.dubbo
+ dubbo-metrics-api
+ ${project.parent.version}
+
+
org.apache.dubbo
dubbo-metrics-default
${project.parent.version}
+
+ org.apache.dubbo
+ dubbo-metrics-registry
+ ${project.parent.version}
+
+
org.apache.dubbo
dubbo-metrics-metadata
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java
index c526864ab4..f605c6d09e 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java
@@ -51,6 +51,9 @@ import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.metadata.report.MetadataReportFactory;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
+import org.apache.dubbo.metrics.model.TimePair;
+import org.apache.dubbo.metrics.registry.event.RegistryEvent;
import org.apache.dubbo.metrics.report.MetricsReporter;
import org.apache.dubbo.metrics.report.MetricsReporterFactory;
import org.apache.dubbo.metrics.service.MetricsServiceExporter;
@@ -825,10 +828,15 @@ public class DefaultApplicationDeployer extends AbstractDeployercompile
true
+
+ org.apache.dubbo
+ dubbo-metrics-registry
+ ${project.version}
+ compile
+ true
+
org.apache.dubbo
dubbo-metrics-prometheus
@@ -502,6 +509,7 @@
org.apache.dubbo:dubbo-metadata-report-zookeeper
org.apache.dubbo:dubbo-metrics-api
org.apache.dubbo:dubbo-metrics-default
+ org.apache.dubbo:dubbo-metrics-registry
org.apache.dubbo:dubbo-metrics-metadata
org.apache.dubbo:dubbo-metrics-prometheus
org.apache.dubbo:dubbo-monitor-api
diff --git a/dubbo-distribution/dubbo-bom/pom.xml b/dubbo-distribution/dubbo-bom/pom.xml
index 42b26038cd..4b5b5fcd51 100644
--- a/dubbo-distribution/dubbo-bom/pom.xml
+++ b/dubbo-distribution/dubbo-bom/pom.xml
@@ -235,6 +235,11 @@
dubbo-metrics-default
${project.version}
+
+ org.apache.dubbo
+ dubbo-metrics-registry
+ ${project.version}
+
org.apache.dubbo
dubbo-metrics-prometheus
diff --git a/dubbo-metrics/dubbo-metrics-api/pom.xml b/dubbo-metrics/dubbo-metrics-api/pom.xml
index 7ee8df194d..3c31ae389c 100644
--- a/dubbo-metrics/dubbo-metrics-api/pom.xml
+++ b/dubbo-metrics/dubbo-metrics-api/pom.xml
@@ -36,11 +36,6 @@
dubbo-common
${project.parent.version}
-
- org.apache.dubbo
- dubbo-cluster
- ${project.parent.version}
-
org.apache.dubbo
dubbo-rpc-api
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java
index 6f5df6660b..c3f187c82e 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java
@@ -71,7 +71,7 @@ public class SimpleMetricsEventMulticaster implements MetricsEventMulticaster {
publishTimeEvent(event, metricsLifeListener -> metricsLifeListener.onEventError(event));
}
- @SuppressWarnings({"rawtypes", "unchecked"})
+ @SuppressWarnings({"rawtypes"})
private void publishTimeEvent(MetricsEvent event, Consumer consumer) {
if (event instanceof EmptyEvent) {
return;
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsKey.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsKey.java
index 96c879c8dd..39cecbfe49 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsKey.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsKey.java
@@ -23,7 +23,7 @@ public enum MetricsKey {
// provider metrics key
METRIC_REQUESTS("dubbo.%s.requests.total", "Total Requests"),
METRIC_REQUESTS_SUCCEED("dubbo.%s.requests.succeed.total", "Succeed Requests"),
- METRIC_REQUEST_BUSINESS_FAILED("dubbo.%s.requests.business.failed.total","Failed Business Requests"),
+ METRIC_REQUEST_BUSINESS_FAILED("dubbo.%s.requests.business.failed.total", "Failed Business Requests"),
METRIC_REQUESTS_PROCESSING("dubbo.%s.requests.processing", "Processing Requests"),
METRIC_REQUESTS_TIMEOUT("dubbo.%s.requests.timeout.total", "Total Timeout Failed Requests"),
METRIC_REQUESTS_LIMIT("dubbo.%s.requests.limit.total", "Total Limit Failed Requests"),
@@ -59,6 +59,26 @@ public enum MetricsKey {
GENERIC_METRIC_RT_P99("dubbo.%s.rt.seconds.p99", "Response Time P99"),
GENERIC_METRIC_RT_P95("dubbo.%s.rt.seconds.p95", "Response Time P95"),
+ // register metrics key
+ REGISTER_METRIC_REQUESTS("dubbo.registry.register.requests.total", "Total Register Requests"),
+ REGISTER_METRIC_REQUESTS_SUCCEED("dubbo.registry.register.requests.succeed.total", "Succeed Register Requests"),
+ REGISTER_METRIC_REQUESTS_FAILED("dubbo.registry.register.requests.failed.total", "Failed Register Requests"),
+
+ // subscribe metrics key
+ SUBSCRIBE_METRIC_NUM("dubbo.registry.subscribe.num.total", "Total Subscribe Num"),
+ SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.registry.subscribe.num.succeed.total", "Succeed Subscribe Num"),
+ SUBSCRIBE_METRIC_NUM_FAILED("dubbo.registry.subscribe.num.failed.total", "Failed Subscribe Num"),
+
+ // directory metrics key
+ DIRECTORY_METRIC_NUM_CURRENT("dubbo.registry.directory.num.current", "Current Directory Urls"),
+ DIRECTORY_METRIC_NUM_VALID("dubbo.registry.directory.num.valid.total", "Valid Directory Urls"),
+ DIRECTORY_METRIC_NUM_UN_VALID("dubbo.registry.directory.num.un_valid.total", "UnValid Directory Urls"),
+ DIRECTORY_METRIC_NUM_DISABLE("dubbo.registry.directory.num.disable.total", "Disable Directory Urls"),
+ DIRECTORY_METRIC_NUM_RECOVER_DISABLE("dubbo.registry.directory.num.recover.disable.total", "Recover Disable Directory Urls"),
+
+ NOTIFY_METRIC_REQUESTS("dubbo.registry.notify.requests.total", "Total Notify Requests"),
+ NOTIFY_METRIC_NUM_LAST("dubbo.registry.notify.num.last", "Last Notify Nums"),
+
THREAD_POOL_CORE_SIZE("dubbo.thread.pool.core.size", "Thread Pool Core Size"),
THREAD_POOL_LARGEST_SIZE("dubbo.thread.pool.largest.size", "Thread Pool Largest Size"),
THREAD_POOL_MAX_SIZE("dubbo.thread.pool.max.size", "Thread Pool Max Size"),
@@ -85,6 +105,7 @@ public enum MetricsKey {
public final String getName() {
return this.name;
}
+
public final String getNameByType(String type) {
return String.format(name, type);
}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/TimePair.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/TimePair.java
index 3994fe9dd2..70e0aba1d6 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/TimePair.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/TimePair.java
@@ -21,6 +21,7 @@ public class TimePair {
private final long begin;
private long end;
+ private static final TimePair empty = new TimePair(0L);
public TimePair(long currentTimeMillis) {
this.begin = currentTimeMillis;
@@ -37,4 +38,8 @@ public class TimePair {
public long calc() {
return end - begin;
}
+
+ public static TimePair empty() {
+ return empty;
+ }
}
diff --git a/dubbo-metrics/dubbo-metrics-default/pom.xml b/dubbo-metrics/dubbo-metrics-default/pom.xml
index 71be413c6a..bc4165d765 100644
--- a/dubbo-metrics/dubbo-metrics-default/pom.xml
+++ b/dubbo-metrics/dubbo-metrics-default/pom.xml
@@ -46,5 +46,11 @@
micrometer-tracing-integration-test
test
+
+ org.apache.dubbo
+ dubbo-cluster
+ ${project.parent.version}
+ compile
+
diff --git a/dubbo-metrics/dubbo-metrics-registry/pom.xml b/dubbo-metrics/dubbo-metrics-registry/pom.xml
new file mode 100644
index 0000000000..86f190ff76
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/pom.xml
@@ -0,0 +1,40 @@
+
+
+ 4.0.0
+
+ org.apache.dubbo
+ dubbo-metrics
+ ${revision}
+ ../pom.xml
+
+ dubbo-metrics-registry
+ jar
+ ${project.artifactId}
+ The metrics module of dubbo project
+
+ false
+
+
+
+ org.apache.dubbo
+ dubbo-metrics-api
+ ${project.parent.version}
+
+
+
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/RegistryMetricsCollector.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/RegistryMetricsCollector.java
new file mode 100644
index 0000000000..c30b7c0f11
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/RegistryMetricsCollector.java
@@ -0,0 +1,123 @@
+/*
+ * 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.registry.collector;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.context.ConfigManager;
+import org.apache.dubbo.metrics.collector.ApplicationMetricsCollector;
+import org.apache.dubbo.metrics.collector.MetricsCollector;
+import org.apache.dubbo.metrics.event.MetricsEvent;
+import org.apache.dubbo.metrics.event.MetricsEventMulticaster;
+import org.apache.dubbo.metrics.model.sample.MetricSample;
+import org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite;
+import org.apache.dubbo.metrics.registry.event.RegistryEvent;
+import org.apache.dubbo.metrics.registry.event.RegistryMetricsEventMulticaster;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+
+/**
+ * Registry implementation of {@link MetricsCollector}
+ */
+@Activate
+public class RegistryMetricsCollector implements ApplicationMetricsCollector {
+
+ private Boolean collectEnabled = null;
+ private final RegistryStatComposite stats;
+ private final MetricsEventMulticaster registryMulticaster;
+ private final ApplicationModel applicationModel;
+
+ public RegistryMetricsCollector(ApplicationModel applicationModel) {
+ this.stats = new RegistryStatComposite();
+ this.registryMulticaster = new RegistryMetricsEventMulticaster();
+ this.applicationModel = applicationModel;
+ }
+
+ 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.getEnableRegistryMetrics()));
+ }
+ return Optional.ofNullable(collectEnabled).orElse(false);
+ }
+
+ public void setNum(RegistryEvent.Type registryType, String applicationName, Map lastNumMap) {
+ lastNumMap.forEach((serviceKey, num) ->
+ this.stats.setServiceKey(registryType, applicationName, serviceKey, num));
+ }
+
+ public void setNum(RegistryEvent.Type registryType, String applicationName, Integer num) {
+ this.stats.setApplicationKey(registryType, applicationName, num);
+ }
+
+
+ @Override
+ public void increment(String applicationName, RegistryEvent.Type registryType) {
+ this.stats.increment(registryType, applicationName);
+ }
+
+ @Override
+ public void addRT(String applicationName, String registryOpType, Long responseTime) {
+ stats.calcRt(applicationName, registryOpType, responseTime);
+ }
+
+ @Override
+ public List collect() {
+ if (!isCollectEnabled()) {
+ new ArrayList<>();
+ }
+ List list = new ArrayList<>();
+ list.addAll(stats.exportNumMetrics());
+ list.addAll(stats.exportRtMetrics());
+ list.addAll(stats.exportSkMetrics());
+
+ return list;
+ }
+
+ @Override
+ public boolean isSupport(MetricsEvent event) {
+ return event instanceof RegistryEvent;
+ }
+
+ @Override
+ public void onEvent(RegistryEvent event) {
+ registryMulticaster.publishEvent(event);
+ }
+
+
+ @Override
+ public void onEventFinish(RegistryEvent event) {
+ registryMulticaster.publishFinishEvent(event);
+ }
+
+ @Override
+ public void onEventError(RegistryEvent event) {
+ registryMulticaster.publishErrorEvent(event);
+ }
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/stat/RegistryStatComposite.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/stat/RegistryStatComposite.java
new file mode 100644
index 0000000000..1d955cd7a7
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/stat/RegistryStatComposite.java
@@ -0,0 +1,240 @@
+/*
+ * 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.registry.collector.stat;
+
+import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
+import org.apache.dubbo.metrics.collector.MetricsCollector;
+import org.apache.dubbo.metrics.model.ApplicationMetric;
+import org.apache.dubbo.metrics.model.MetricsCategory;
+import org.apache.dubbo.metrics.model.MetricsKey;
+import org.apache.dubbo.metrics.model.MetricsKeyWrapper;
+import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
+import org.apache.dubbo.metrics.registry.event.RegistryEvent;
+import org.apache.dubbo.metrics.report.MetricsExport;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.LongAccumulator;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+/**
+ * As a data aggregator, use internal data containers calculates and classifies
+ * the registry data collected by {@link MetricsCollector MetricsCollector}, and
+ * provides an {@link MetricsExport MetricsExport} interface for exporting standard output formats.
+ */
+public class RegistryStatComposite implements MetricsExport {
+
+
+ public Map> numStats = new ConcurrentHashMap<>();
+ public Map> skStats = new ConcurrentHashMap<>();
+ public List> rtStats = new ArrayList<>();
+ public static String OP_TYPE_REGISTER = "register";
+ public static String OP_TYPE_SUBSCRIBE = "subscribe";
+ public static String OP_TYPE_NOTIFY = "notify";
+
+ public RegistryStatComposite() {
+ for (RegistryEvent.Type type : RegistryEvent.Type.values()) {
+ numStats.put(type, new ConcurrentHashMap<>());
+ }
+
+ rtStats.addAll(initStats(OP_TYPE_REGISTER));
+ rtStats.addAll(initStats(OP_TYPE_SUBSCRIBE));
+ rtStats.addAll(initStats(OP_TYPE_NOTIFY));
+ }
+
+ private List> initStats(String registryOpType) {
+ List> singleRtStats = new ArrayList<>();
+ singleRtStats.add(new AtomicLongContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_LAST)));
+ singleRtStats.add(new LongAccumulatorContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_MIN), new LongAccumulator(Long::min, Long.MAX_VALUE)));
+ singleRtStats.add(new LongAccumulatorContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_MAX), new LongAccumulator(Long::max, Long.MIN_VALUE)));
+ singleRtStats.add(new AtomicLongContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_SUM), (responseTime, longAccumulator) -> longAccumulator.addAndGet(responseTime)));
+ // AvgContainer is a special counter that stores the number of times but outputs function of sum/times
+ AtomicLongContainer avgContainer = new AtomicLongContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_AVG), (k, v) -> v.incrementAndGet());
+ avgContainer.setValueSupplier(applicationName -> {
+ LongContainer extends Number> totalContainer = rtStats.stream().filter(longContainer -> longContainer.isKeyWrapper(MetricsKey.GENERIC_METRIC_RT_SUM, registryOpType)).findFirst().get();
+ AtomicLong totalRtTimes = avgContainer.get(applicationName);
+ AtomicLong totalRtSum = (AtomicLong) totalContainer.get(applicationName);
+ return totalRtSum.get() / totalRtTimes.get();
+ });
+ singleRtStats.add(avgContainer);
+ return singleRtStats;
+ }
+
+ public void setApplicationKey(RegistryEvent.Type type, String applicationName, int num) {
+ if (!numStats.containsKey(type)) {
+ return;
+ }
+ numStats.get(type).computeIfAbsent(applicationName, k -> new AtomicLong(0L)).set(num);
+ }
+
+ public void setServiceKey(RegistryEvent.Type type, String applicationName, String serviceKey, int num) {
+ if (!skStats.containsKey(type)) {
+ return;
+ }
+ skStats.get(type).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).set(num);
+ }
+
+ public void increment(RegistryEvent.Type type, String applicationName) {
+ if (!numStats.containsKey(type)) {
+ return;
+ }
+ numStats.get(type).computeIfAbsent(applicationName, k -> new AtomicLong(0L)).incrementAndGet();
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public void calcRt(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());
+ container.getConsumerFunc().accept(responseTime, current);
+ }
+ }
+
+ @Override
+ public List exportNumMetrics() {
+ List list = new ArrayList<>();
+ for (RegistryEvent.Type type : numStats.keySet()) {
+ Map stringAtomicLongMap = numStats.get(type);
+ for (String applicationName : stringAtomicLongMap.keySet()) {
+ list.add(convertToSample(applicationName, type, MetricsCategory.REGISTRY, stringAtomicLongMap.get(applicationName)));
+ }
+ }
+ return list;
+ }
+
+ @Override
+ public List exportRtMetrics() {
+ List list = new ArrayList<>();
+ for (LongContainer extends Number> rtContainer : rtStats) {
+ MetricsKeyWrapper metricsKeyWrapper = rtContainer.getMetricsKeyWrapper();
+ for (Map.Entry entry : rtContainer.entrySet()) {
+ list.add(new GaugeMetricSample(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), ApplicationMetric.getTagsByName(entry.getKey()), MetricsCategory.RT, () -> rtContainer.getValueSupplier().apply(entry.getKey())));
+ }
+ }
+ return list;
+ }
+
+ public List exportSkMetrics() {
+ List list = new ArrayList<>();
+ for (RegistryEvent.Type type : skStats.keySet()) {
+ Map stringAtomicLongMap = skStats.get(type);
+ for (ServiceKeyMetric serviceKeyMetric : stringAtomicLongMap.keySet()) {
+ list.add(new GaugeMetricSample(type.getMetricsKey(), serviceKeyMetric.getTags(), MetricsCategory.REGISTRY, stringAtomicLongMap.get(serviceKeyMetric)::get));
+ }
+ }
+ return list;
+ }
+
+ public GaugeMetricSample convertToSample(String applicationName, RegistryEvent.Type type, MetricsCategory category, AtomicLong targetNumber) {
+ return new GaugeMetricSample(type.getMetricsKey(), ApplicationMetric.getTagsByName(applicationName), category, targetNumber::get);
+ }
+
+
+ /**
+ * Collect Number type data
+ *
+ * @param
+ */
+ public static class LongContainer extends ConcurrentHashMap {
+
+ /**
+ * Provide the metric type name
+ */
+ private final MetricsKeyWrapper metricsKeyWrapper;
+ /**
+ * The initial value corresponding to the key is generally 0 of different data types
+ */
+ private final Function initFunc;
+ /**
+ * Statistical data calculation function, which can be self-increment, self-decrement, or more complex avg function
+ */
+ private final BiConsumer consumerFunc;
+ /**
+ * Data output function required by {@link GaugeMetricSample GaugeMetricSample}
+ */
+ private Function valueSupplier;
+
+
+ public LongContainer(MetricsKeyWrapper metricsKeyWrapper, Supplier initFunc, BiConsumer consumerFunc) {
+ this.metricsKeyWrapper = metricsKeyWrapper;
+ this.initFunc = s -> initFunc.get();
+ this.consumerFunc = consumerFunc;
+ this.valueSupplier = k -> this.get(k).longValue();
+ }
+
+ public boolean specifyType(String type) {
+ return type.equals(getMetricsKeyWrapper().getType());
+ }
+
+ public MetricsKeyWrapper getMetricsKeyWrapper() {
+ return metricsKeyWrapper;
+ }
+
+ public boolean isKeyWrapper(MetricsKey metricsKey, String registryOpType) {
+ return metricsKeyWrapper.isKey(metricsKey,registryOpType);
+ }
+
+ public Function getInitFunc() {
+ return initFunc;
+ }
+
+ public BiConsumer getConsumerFunc() {
+ return consumerFunc;
+ }
+
+ public Function getValueSupplier() {
+ return valueSupplier;
+ }
+
+ public void setValueSupplier(Function valueSupplier) {
+ this.valueSupplier = valueSupplier;
+ }
+
+ @Override
+ public String toString() {
+ return "LongContainer{" +
+ "metricsKeyWrapper=" + metricsKeyWrapper +
+ '}';
+ }
+ }
+
+ public static class AtomicLongContainer extends LongContainer {
+
+ public AtomicLongContainer(MetricsKeyWrapper metricsKeyWrapper) {
+ super(metricsKeyWrapper, AtomicLong::new, (responseTime, longAccumulator) -> longAccumulator.set(responseTime));
+ }
+
+ public AtomicLongContainer(MetricsKeyWrapper metricsKeyWrapper, BiConsumer consumerFunc) {
+ super(metricsKeyWrapper, AtomicLong::new, consumerFunc);
+ }
+
+ }
+
+ public static class LongAccumulatorContainer extends LongContainer {
+ public LongAccumulatorContainer(MetricsKeyWrapper metricsKeyWrapper, LongAccumulator accumulator) {
+ super(metricsKeyWrapper, () -> accumulator, (responseTime, longAccumulator) -> longAccumulator.accumulate(responseTime));
+ }
+ }
+
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/stat/ServiceKeyMetric.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/stat/ServiceKeyMetric.java
new file mode 100644
index 0000000000..0b39ff8376
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/stat/ServiceKeyMetric.java
@@ -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.registry.collector.stat;
+
+import org.apache.dubbo.metrics.model.Metric;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
+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.utils.NetUtils.getLocalHost;
+import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
+
+/**
+ * Metric class for service.
+ */
+public class ServiceKeyMetric implements Metric {
+ private final String applicationName;
+ private final String serviceKey;
+
+ public ServiceKeyMetric(String applicationName, String serviceKey) {
+ this.applicationName = applicationName;
+ this.serviceKey = serviceKey;
+ }
+
+ public String getServiceKey() {
+ return serviceKey;
+ }
+
+ public Map getTags() {
+ Map tags = new HashMap<>();
+ tags.put(TAG_IP, getLocalHost());
+ tags.put(TAG_HOSTNAME, getLocalHostName());
+ tags.put(TAG_APPLICATION_NAME, applicationName);
+
+ tags.put(TAG_INTERFACE_KEY, serviceKey);
+ return tags;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ServiceKeyMetric that = (ServiceKeyMetric) o;
+
+ if (!applicationName.equals(that.applicationName)) return false;
+ return serviceKey.equals(that.serviceKey);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = applicationName.hashCode();
+ result = 31 * result + serviceKey.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ServiceKeyMetric{" +
+ "applicationName='" + applicationName + '\'' +
+ ", serviceKey='" + serviceKey + '\'' +
+ '}';
+ }
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsDirectoryListener.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsDirectoryListener.java
new file mode 100644
index 0000000000..27648f962d
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsDirectoryListener.java
@@ -0,0 +1,43 @@
+/*
+ * 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.registry.event;
+
+import org.apache.dubbo.metrics.event.MetricsEvent;
+import org.apache.dubbo.metrics.listener.MetricsListener;
+
+public class MetricsDirectoryListener implements MetricsListener {
+
+ @Override
+ public boolean isSupport(MetricsEvent event) {
+ return event instanceof RegistryEvent.MetricsDirectoryEvent;
+ }
+
+ @Override
+ public void onEvent(RegistryEvent.MetricsDirectoryEvent event) {
+ if (!event.isAvailable()) {
+ return;
+ }
+ if (event.getType().isIncrement()) {
+ event.getCollector().increment(event.getSource().getApplicationName(), event.getType());
+ } else {
+ event.getCollector().setNum(event.getType(), event.getSource().getApplicationName(), event.getSize());
+ }
+ }
+
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsNotifyListener.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsNotifyListener.java
new file mode 100644
index 0000000000..3b5561cb1f
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsNotifyListener.java
@@ -0,0 +1,54 @@
+/*
+ * 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.registry.event;
+
+import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.metrics.event.MetricsEvent;
+import org.apache.dubbo.metrics.listener.MetricsLifeListener;
+
+import static org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite.OP_TYPE_NOTIFY;
+
+/**
+ * The registration center actively pushes Listener, no failure and rt statistics
+ */
+public class MetricsNotifyListener implements MetricsLifeListener {
+
+ protected final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass());
+
+ @Override
+ public boolean isSupport(MetricsEvent event) {
+ return event instanceof RegistryEvent.MetricsNotifyEvent;
+ }
+
+ @Override
+ public void onEvent(RegistryEvent.MetricsNotifyEvent event) {
+ event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.N_TOTAL);
+ }
+
+ @Override
+ public void onEventFinish(RegistryEvent.MetricsNotifyEvent event) {
+ event.getCollector().setNum(RegistryEvent.Type.N_LAST_NUM, event.getSource().getApplicationName(), event.getLastNotifyNum());
+ event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_NOTIFY, event.getTimePair().calc());
+ }
+
+ @Override
+ public void onEventError(RegistryEvent.MetricsNotifyEvent event) {
+ }
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsRegisterListener.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsRegisterListener.java
new file mode 100644
index 0000000000..f3c6352fcf
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsRegisterListener.java
@@ -0,0 +1,52 @@
+/*
+ * 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.registry.event;
+
+import org.apache.dubbo.metrics.event.MetricsEvent;
+import org.apache.dubbo.metrics.listener.MetricsLifeListener;
+
+import static org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite.OP_TYPE_REGISTER;
+
+public class MetricsRegisterListener implements MetricsLifeListener {
+
+
+ @Override
+ public boolean isSupport(MetricsEvent event) {
+ return event instanceof RegistryEvent.MetricsRegisterEvent;
+ }
+
+ @Override
+ public void onEvent(RegistryEvent.MetricsRegisterEvent event) {
+ if (!event.isAvailable()) {
+ return;
+ }
+ event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.R_TOTAL);
+ }
+
+ @Override
+ public void onEventFinish(RegistryEvent.MetricsRegisterEvent event) {
+ event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.R_SUCCEED);
+ event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_REGISTER, event.getTimePair().calc());
+ }
+
+ @Override
+ public void onEventError(RegistryEvent.MetricsRegisterEvent event) {
+ event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.R_FAILED);
+ event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_REGISTER, event.getTimePair().calc());
+ }
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsSubscribeListener.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsSubscribeListener.java
new file mode 100644
index 0000000000..abfc5a0624
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/MetricsSubscribeListener.java
@@ -0,0 +1,52 @@
+/*
+ * 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.registry.event;
+
+import org.apache.dubbo.metrics.event.MetricsEvent;
+import org.apache.dubbo.metrics.listener.MetricsLifeListener;
+
+import static org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite.OP_TYPE_SUBSCRIBE;
+
+public class MetricsSubscribeListener implements MetricsLifeListener {
+
+ @Override
+ public boolean isSupport(MetricsEvent event) {
+ return event instanceof RegistryEvent.MetricsSubscribeEvent;
+ }
+
+ @Override
+ public void onEvent(RegistryEvent.MetricsSubscribeEvent event) {
+ if (!event.isAvailable()) {
+ return;
+ }
+ event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.S_TOTAL);
+ }
+
+ @Override
+ public void onEventFinish(RegistryEvent.MetricsSubscribeEvent event) {
+ event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.S_SUCCEED);
+ event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_SUBSCRIBE, event.getTimePair().calc());
+ }
+
+ @Override
+ public void onEventError(RegistryEvent.MetricsSubscribeEvent event) {
+ event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.S_FAILED);
+ event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_SUBSCRIBE, event.getTimePair().calc());
+ }
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryEvent.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryEvent.java
new file mode 100644
index 0000000000..c13eb2310d
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryEvent.java
@@ -0,0 +1,156 @@
+/*
+ * 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.registry.event;
+
+import org.apache.dubbo.metrics.event.MetricsEvent;
+import org.apache.dubbo.metrics.event.TimeCounter;
+import org.apache.dubbo.metrics.model.MetricsKey;
+import org.apache.dubbo.metrics.model.TimePair;
+import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import java.util.Map;
+
+/**
+ * Registry related events
+ */
+public class RegistryEvent extends MetricsEvent implements TimeCounter {
+ private final TimePair timePair;
+ private final RegistryMetricsCollector collector;
+ private final boolean available;
+
+ public RegistryEvent(ApplicationModel applicationModel, TimePair timePair) {
+ super(applicationModel);
+ this.timePair = timePair;
+ this.collector = applicationModel.getBeanFactory().getBean(RegistryMetricsCollector.class);
+ this.available = this.collector != null && collector.isCollectEnabled();
+ }
+
+ public ApplicationModel getSource() {
+ return (ApplicationModel) source;
+ }
+
+ public RegistryMetricsCollector getCollector() {
+ return collector;
+ }
+
+ public boolean isAvailable() {
+ return available;
+ }
+
+ @Override
+ public TimePair getTimePair() {
+ return timePair;
+ }
+
+ public enum Type {
+ R_TOTAL(MetricsKey.REGISTER_METRIC_REQUESTS),
+ R_SUCCEED(MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED),
+ R_FAILED(MetricsKey.REGISTER_METRIC_REQUESTS_FAILED),
+
+ S_TOTAL(MetricsKey.SUBSCRIBE_METRIC_NUM),
+ S_SUCCEED(MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED),
+ S_FAILED(MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED),
+
+ D_VALID(MetricsKey.DIRECTORY_METRIC_NUM_VALID),
+ D_UN_VALID(MetricsKey.DIRECTORY_METRIC_NUM_UN_VALID),
+ D_DISABLE(MetricsKey.DIRECTORY_METRIC_NUM_DISABLE),
+ D_CURRENT(MetricsKey.DIRECTORY_METRIC_NUM_CURRENT, false),
+ D_RECOVER_DISABLE(MetricsKey.DIRECTORY_METRIC_NUM_RECOVER_DISABLE),
+
+ N_TOTAL(MetricsKey.NOTIFY_METRIC_REQUESTS),
+ N_LAST_NUM(MetricsKey.NOTIFY_METRIC_NUM_LAST),
+ ;
+
+
+ private final MetricsKey metricsKey;
+ private final boolean isIncrement;
+
+
+ Type(MetricsKey metricsKey) {
+ this(metricsKey, true);
+ }
+
+ Type(MetricsKey metricsKey, boolean isIncrement) {
+ this.metricsKey = metricsKey;
+ this.isIncrement = isIncrement;
+ }
+
+ public MetricsKey getMetricsKey() {
+ return metricsKey;
+ }
+
+ public boolean isIncrement() {
+ return isIncrement;
+ }
+ }
+
+ public static class MetricsRegisterEvent extends RegistryEvent {
+
+ public MetricsRegisterEvent(ApplicationModel applicationModel, TimePair timePair) {
+ super(applicationModel, timePair);
+ }
+
+ }
+
+ public static class MetricsSubscribeEvent extends RegistryEvent {
+
+ public MetricsSubscribeEvent(ApplicationModel applicationModel, TimePair timePair) {
+ super(applicationModel, timePair);
+ }
+
+ }
+
+ public static class MetricsNotifyEvent extends RegistryEvent {
+
+ private final Map lastNumMap;
+
+ public MetricsNotifyEvent(ApplicationModel applicationModel, TimePair timePair, Map lastNumMap) {
+ super(applicationModel, timePair);
+ this.lastNumMap = lastNumMap;
+ }
+
+ public Map getLastNotifyNum() {
+ return lastNumMap;
+ }
+ }
+
+ public static class MetricsDirectoryEvent extends RegistryEvent {
+
+ private final RegistryEvent.Type type;
+ private final int size;
+
+ public MetricsDirectoryEvent(ApplicationModel applicationModel, RegistryEvent.Type type) {
+ this(applicationModel, type, 1);
+ }
+
+ public MetricsDirectoryEvent(ApplicationModel applicationModel, RegistryEvent.Type type, int size) {
+ super(applicationModel, TimePair.empty());
+ this.type = type;
+ this.size = size;
+ }
+
+ public RegistryEvent.Type getType() {
+ return type;
+ }
+
+ public int getSize() {
+ return size;
+ }
+ }
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryMetricsEventMulticaster.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryMetricsEventMulticaster.java
new file mode 100644
index 0000000000..566607efdb
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryMetricsEventMulticaster.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.metrics.registry.event;
+
+import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
+
+public final class RegistryMetricsEventMulticaster extends SimpleMetricsEventMulticaster {
+
+ public RegistryMetricsEventMulticaster() {
+ super.addListener(new MetricsRegisterListener());
+ super.addListener(new MetricsSubscribeListener());
+ super.addListener(new MetricsNotifyListener());
+ super.addListener(new MetricsDirectoryListener());
+
+ setAvailable();
+ }
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector b/dubbo-metrics/dubbo-metrics-registry/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector
new file mode 100644
index 0000000000..3b14cf6c7b
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector
@@ -0,0 +1 @@
+registry-collector=org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsCollectorTest.java b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsCollectorTest.java
new file mode 100644
index 0000000000..d4e8f34cec
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsCollectorTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.registry.metrics.collector;
+
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
+import org.apache.dubbo.metrics.model.MetricsKey;
+import org.apache.dubbo.metrics.model.MetricsKeyWrapper;
+import org.apache.dubbo.metrics.model.TimePair;
+import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
+import org.apache.dubbo.metrics.model.sample.MetricSample;
+import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
+import org.apache.dubbo.metrics.registry.event.RegistryEvent;
+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.MetricsConstants.TAG_APPLICATION_NAME;
+import static org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite.OP_TYPE_REGISTER;
+
+
+class RegistryMetricsCollectorTest {
+
+ private ApplicationModel applicationModel;
+
+ @BeforeEach
+ public void setup() {
+ FrameworkModel frameworkModel = FrameworkModel.defaultModel();
+ applicationModel = frameworkModel.newApplication();
+ ApplicationConfig config = new ApplicationConfig();
+ config.setName("MockMetrics");
+
+ applicationModel.getApplicationConfigManager().setApplication(config);
+
+ }
+
+ @AfterEach
+ public void teardown() {
+ applicationModel.destroy();
+ }
+
+ @Test
+ void testPushMetrics() throws InterruptedException {
+
+ TimePair timePair = TimePair.start();
+ GlobalMetricsEventMulticaster eventMulticaster = applicationModel.getBeanFactory().getOrRegisterBean(GlobalMetricsEventMulticaster.class);
+ RegistryMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class);
+ collector.setCollectEnabled(true);
+
+ eventMulticaster.publishEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
+ List metricSamples = collector.collect();
+
+ // push success +1
+ Assertions.assertEquals(metricSamples.size(), 1);
+ Assertions.assertTrue(metricSamples.get(0) instanceof GaugeMetricSample);
+
+ eventMulticaster.publishFinishEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
+ // push finish rt +1
+ metricSamples = collector.collect();
+ //num(total+success) + rt(5) = 7
+ Assertions.assertEquals(metricSamples.size(), 7);
+ long c1 = timePair.calc();
+ TimePair lastTimePair = TimePair.start();
+ eventMulticaster.publishEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, lastTimePair));
+ Thread.sleep(50);
+ // push error rt +1
+ eventMulticaster.publishErrorEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, lastTimePair));
+ long c2 = lastTimePair.calc();
+ metricSamples = collector.collect();
+
+ // num(total+success+error) + rt(5)
+ Assertions.assertEquals(metricSamples.size(), 8);
+
+ // calc rt
+ for (MetricSample sample : metricSamples) {
+ Map tags = sample.getTags();
+ Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationModel.getApplicationName());
+ }
+ Map sampleMap = metricSamples.stream().collect(Collectors.toMap(MetricSample::getName, k -> {
+ Number number = ((GaugeMetricSample) k).getSupplier().get();
+ return number.longValue();
+ }));
+
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_LAST).targetKey()), lastTimePair.calc());
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_MIN).targetKey()), Math.min(c1, c2));
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_MAX).targetKey()), Math.max(c1, c2));
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_AVG).targetKey()), (c1 + c2) / 2);
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_SUM).targetKey()), c1 + c2);
+ }
+
+
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsSampleTest.java b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsSampleTest.java
new file mode 100644
index 0000000000..92025d71c9
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsSampleTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.registry.metrics.collector;
+
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.metrics.model.MetricsKey;
+import org.apache.dubbo.metrics.model.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;
+import org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite;
+import org.apache.dubbo.metrics.registry.event.RegistryEvent;
+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.MetricsConstants.TAG_APPLICATION_NAME;
+
+class RegistryMetricsSampleTest {
+
+ private ApplicationModel applicationModel;
+
+ @BeforeEach
+ public void setup() {
+ FrameworkModel frameworkModel = FrameworkModel.defaultModel();
+ applicationModel = frameworkModel.newApplication();
+ ApplicationConfig config = new ApplicationConfig();
+ config.setName("MockMetrics");
+ applicationModel.getApplicationConfigManager().setApplication(config);
+ }
+
+ @AfterEach
+ public void teardown() {
+ applicationModel.destroy();
+ }
+
+ @Test
+ void testRegisterMetrics() {
+ }
+
+ @Test
+ void testRTMetrics() {
+ RegistryMetricsCollector collector = new RegistryMetricsCollector(applicationModel);
+ collector.setCollectEnabled(true);
+ String applicationName = applicationModel.getApplicationName();
+ collector.addRT(applicationName, RegistryStatComposite.OP_TYPE_REGISTER, 10L);
+ collector.addRT(applicationName, RegistryStatComposite.OP_TYPE_REGISTER, 0L);
+
+ List samples = collector.collect();
+ for (MetricSample sample : samples) {
+ Map tags = sample.getTags();
+ Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationName);
+ }
+
+ Map sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> {
+ Number number = ((GaugeMetricSample) k).getSupplier().get();
+ return number.longValue();
+ }));
+
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_LAST).targetKey()), 0L);
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_MIN).targetKey()), 0L);
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_MAX).targetKey()), 10L);
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_AVG).targetKey()), 5L);
+ Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_SUM).targetKey()), 10L);
+ }
+
+ @Test
+ void testListener() {
+ RegistryMetricsCollector collector = new RegistryMetricsCollector(applicationModel);
+ collector.setCollectEnabled(true);
+ String applicationName = applicationModel.getApplicationName();
+ collector.increment(applicationName,RegistryEvent.Type.R_TOTAL);
+ }
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/model/MethodMetricTest.java b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/model/MethodMetricTest.java
new file mode 100644
index 0000000000..44beb3a608
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/model/MethodMetricTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.registry.metrics.model;
+
+import org.apache.dubbo.metrics.model.MethodMetric;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+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.common.constants.MetricsConstants.TAG_GROUP_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.constants.MetricsConstants.TAG_VERSION_KEY;
+import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
+import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
+
+class MethodMetricTest {
+
+ private static final String applicationName = null;
+ private static String interfaceName;
+ private static String methodName;
+ private static String group;
+ private static String version;
+ private static RpcInvocation invocation;
+
+ @BeforeAll
+ public static void setup() {
+ 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);
+ }
+
+ @Test
+ void test() {
+ MethodMetric metric = new MethodMetric(applicationName, invocation);
+ Assertions.assertEquals(metric.getInterfaceName(), interfaceName);
+ Assertions.assertEquals(metric.getMethodName(), methodName);
+ Assertions.assertEquals(metric.getGroup(), group);
+ Assertions.assertEquals(metric.getVersion(), version);
+
+ Map tags = metric.getTags();
+ Assertions.assertEquals(tags.get(TAG_IP), getLocalHost());
+ Assertions.assertEquals(tags.get(TAG_HOSTNAME), getLocalHostName());
+ Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationName);
+
+ 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);
+ }
+}
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/model/sample/GaugeMetricSampleTest.java b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/model/sample/GaugeMetricSampleTest.java
new file mode 100644
index 0000000000..bfa6d2e176
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/model/sample/GaugeMetricSampleTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.registry.metrics.model.sample;
+
+import org.apache.dubbo.metrics.model.MetricsCategory;
+import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
+import org.apache.dubbo.metrics.model.sample.MetricSample;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Supplier;
+
+class GaugeMetricSampleTest {
+
+ private static String name;
+ private static String description;
+ private static Map tags;
+ private static MetricsCategory category;
+ private static String baseUnit;
+ private static Supplier supplier;
+
+ @BeforeAll
+ public static void setup() {
+ name = "test";
+ description = "test";
+ tags = new HashMap<>();
+ category = MetricsCategory.REQUESTS;
+ baseUnit = "byte";
+ supplier = () -> 1;
+ }
+
+ @Test
+ void test() {
+ GaugeMetricSample sample = new GaugeMetricSample(name, description, tags, category, baseUnit, supplier);
+ Assertions.assertEquals(sample.getName(), name);
+ Assertions.assertEquals(sample.getDescription(), description);
+ Assertions.assertEquals(sample.getTags(), tags);
+ Assertions.assertEquals(sample.getType(), MetricSample.Type.GAUGE);
+ Assertions.assertEquals(sample.getCategory(), category);
+ Assertions.assertEquals(sample.getBaseUnit(), baseUnit);
+ Assertions.assertEquals(sample.getSupplier().get(), 1);
+ sample.setSupplier(() -> 2);
+ Assertions.assertEquals(sample.getSupplier().get(), 2);
+ }
+}
diff --git a/dubbo-metrics/pom.xml b/dubbo-metrics/pom.xml
index 835c2b1b44..d5527ecf7c 100644
--- a/dubbo-metrics/pom.xml
+++ b/dubbo-metrics/pom.xml
@@ -20,6 +20,7 @@
dubbo-metrics-api
dubbo-metrics-default
+ dubbo-metrics-registry
dubbo-metrics-metadata
dubbo-metrics-prometheus
diff --git a/dubbo-registry/dubbo-registry-api/pom.xml b/dubbo-registry/dubbo-registry-api/pom.xml
index f9c580f8c9..4c3a15f353 100644
--- a/dubbo-registry/dubbo-registry-api/pom.xml
+++ b/dubbo-registry/dubbo-registry-api/pom.xml
@@ -98,5 +98,12 @@
${project.parent.version}
compile
+
+
+ org.apache.dubbo
+ dubbo-metrics-registry
+ ${project.parent.version}
+ compile
+
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
index c6eb7a83ec..0859c1e9e2 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
@@ -16,6 +16,32 @@
*/
package org.apache.dubbo.registry.client.event.listener;
+import org.apache.dubbo.common.ProtocolServiceKey;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.URLBuilder;
+import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
+import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.ConcurrentHashSet;
+import org.apache.dubbo.metadata.MetadataInfo;
+import org.apache.dubbo.metadata.MetadataInfo.ServiceInfo;
+import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
+import org.apache.dubbo.metrics.model.TimePair;
+import org.apache.dubbo.metrics.registry.event.RegistryEvent;
+import org.apache.dubbo.registry.NotifyListener;
+import org.apache.dubbo.registry.client.DefaultServiceInstance;
+import org.apache.dubbo.registry.client.ServiceDiscovery;
+import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.registry.client.event.RetryServiceInstancesChangedEvent;
+import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
+import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
+import org.apache.dubbo.registry.client.metadata.ServiceInstanceNotificationCustomizer;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -32,28 +58,6 @@ import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.apache.dubbo.common.ProtocolServiceKey;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.URLBuilder;
-import org.apache.dubbo.common.constants.CommonConstants;
-import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.ConcurrentHashSet;
-import org.apache.dubbo.metadata.MetadataInfo;
-import org.apache.dubbo.metadata.MetadataInfo.ServiceInfo;
-import org.apache.dubbo.registry.NotifyListener;
-import org.apache.dubbo.registry.client.DefaultServiceInstance;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.registry.client.ServiceInstance;
-import org.apache.dubbo.registry.client.event.RetryServiceInstancesChangedEvent;
-import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
-import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
-import org.apache.dubbo.registry.client.metadata.ServiceInstanceNotificationCustomizer;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.dubbo.rpc.model.ScopeModelUtil;
-
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_REFRESH_ADDRESS;
@@ -87,6 +91,7 @@ public class ServiceInstancesChangedListener {
private final ScheduledExecutorService scheduler;
private volatile boolean hasEmptyMetadata;
private final Set serviceInstanceNotificationCustomizers;
+ private final ApplicationModel applicationModel;
public ServiceInstancesChangedListener(Set serviceNames, ServiceDiscovery serviceDiscovery) {
@@ -99,6 +104,7 @@ public class ServiceInstancesChangedListener {
ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(serviceDiscovery == null || serviceDiscovery.getUrl() == null ? null : serviceDiscovery.getUrl().getScopeModel());
this.scheduler = applicationModel.getBeanFactory().getBean(FrameworkExecutorRepository.class).getMetadataRetryExecutor();
this.serviceInstanceNotificationCustomizers = applicationModel.getExtensionLoader(ServiceInstanceNotificationCustomizer.class).getSupportedExtensionInstances();
+ this.applicationModel = applicationModel;
}
/**
@@ -398,6 +404,13 @@ public class ServiceInstancesChangedListener {
* race condition is protected by onEvent/doOnEvent
*/
protected void notifyAddressChanged() {
+
+ ScopeBeanFactory beanFactory = applicationModel.getFrameworkModel().getBeanFactory();
+ SimpleMetricsEventMulticaster eventMulticaster = beanFactory.getOrRegisterBean(SimpleMetricsEventMulticaster.class);
+
+ TimePair timePair = TimePair.start();
+ eventMulticaster.publishEvent(new RegistryEvent.MetricsNotifyEvent(applicationModel, timePair, null));
+ Map lastNumMap = new HashMap<>();
// 1 different services
listeners.forEach((serviceKey, listenerSet) -> {
// 2 multiple subscription listener of the same service
@@ -407,8 +420,11 @@ public class ServiceInstancesChangedListener {
List urls = toUrlsWithEmpty(getAddresses(listenerWithKey.getProtocolServiceKey(), notifyListener.getConsumerUrl()));
logger.info("Notify service " + listenerWithKey.getProtocolServiceKey() + " with urls " + urls.size());
notifyListener.notify(urls);
+ lastNumMap.put(serviceKey, urls.size());
}
});
+ eventMulticaster.publishFinishEvent(new RegistryEvent.MetricsNotifyEvent(applicationModel, timePair, lastNumMap));
+
}
protected List toUrlsWithEmpty(List urls) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
index a994f1f1c7..65c8ef3190 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
@@ -16,19 +16,6 @@
*/
package org.apache.dubbo.registry.integration;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
@@ -43,6 +30,9 @@ import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
+import org.apache.dubbo.metrics.model.TimePair;
+import org.apache.dubbo.metrics.registry.event.RegistryEvent;
import org.apache.dubbo.registry.AddressListener;
import org.apache.dubbo.remoting.Constants;
import org.apache.dubbo.rpc.Invoker;
@@ -53,8 +43,22 @@ import org.apache.dubbo.rpc.cluster.Router;
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
import org.apache.dubbo.rpc.cluster.router.state.BitList;
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DISABLED_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
@@ -110,11 +114,18 @@ public class RegistryDirectory extends DynamicDirectory {
super(serviceType, url);
moduleModel = getModuleModel(url.getScopeModel());
consumerConfigurationListener = getConsumerConfigurationListener(moduleModel);
+
}
@Override
public void subscribe(URL url) {
+ ApplicationModel applicationModel = url.getApplicationModel();
+ GlobalMetricsEventMulticaster eventMulticaster = applicationModel.getBeanFactory().getBean(GlobalMetricsEventMulticaster.class);
+ TimePair timePair = TimePair.start();
+
+ eventMulticaster.publishEvent(new RegistryEvent.MetricsSubscribeEvent(applicationModel, timePair));
super.subscribe(url);
+ eventMulticaster.publishFinishEvent(new RegistryEvent.MetricsSubscribeEvent(applicationModel, timePair));
if (moduleModel.getModelEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
consumerConfigurationListener.addNotifyListener(this);
referenceConfigurationListener = new ReferenceConfigurationListener(moduleModel, this, url);
@@ -233,7 +244,7 @@ public class RegistryDirectory extends DynamicDirectory {
// use local reference to avoid NPE as this.cachedInvokerUrls will be set null by destroyAllInvokers().
Set localCachedInvokerUrls = this.cachedInvokerUrls;
if (invokerUrls.isEmpty()) {
- if(CollectionUtils.isNotEmpty(localCachedInvokerUrls)){
+ if (CollectionUtils.isNotEmpty(localCachedInvokerUrls)) {
// 1-4 Empty address.
logger.warn(REGISTRY_EMPTY_ADDRESS, "configuration ", "",
"Service" + serviceKey + " received empty address list with no EMPTY protocol set, trigger empty protection.");
diff --git a/dubbo-test/dubbo-dependencies-all/pom.xml b/dubbo-test/dubbo-dependencies-all/pom.xml
index 66f84b58f6..8922e63208 100644
--- a/dubbo-test/dubbo-dependencies-all/pom.xml
+++ b/dubbo-test/dubbo-dependencies-all/pom.xml
@@ -148,6 +148,11 @@
org.apache.dubbo
dubbo-metrics-default
+
+ org.apache.dubbo
+ dubbo-metrics-registry
+
+
org.apache.dubbo
dubbo-metrics-metadata