This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.2
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.2 by this push:
new c041fa1f93 Observability task: registration center (#11493)
c041fa1f93 is described below
commit c041fa1f9331a96f65f5fe006f035d4679b41c04
Author: wxbty <[email protected]>
AuthorDate: Sat Feb 25 17:22:44 2023 +0800
Observability task: registration center (#11493)
---
dubbo-cluster/pom.xml | 6 +
.../rpc/cluster/directory/AbstractDirectory.java | 47 ++--
.../rpc/cluster/directory/StaticDirectoryTest.java | 3 +
.../support/AbstractClusterInvokerTest.java | 19 +-
.../support/ConnectivityValidationTest.java | 3 +
.../support/FailoverClusterInvokerTest.java | 12 +-
.../support/wrapper/MockClusterInvokerTest.java | 3 +
.../wrapper/MockProviderRpcExceptionTest.java | 3 +
.../org/apache/dubbo/config/MetricsConfig.java | 15 +-
dubbo-config/dubbo-config-api/pom.xml | 12 ++
.../config/deploy/DefaultApplicationDeployer.java | 8 +
dubbo-distribution/dubbo-all/pom.xml | 8 +
dubbo-distribution/dubbo-bom/pom.xml | 5 +
dubbo-metrics/dubbo-metrics-api/pom.xml | 5 -
.../event/SimpleMetricsEventMulticaster.java | 2 +-
.../org/apache/dubbo/metrics/model/MetricsKey.java | 23 +-
.../org/apache/dubbo/metrics/model/TimePair.java | 5 +
dubbo-metrics/dubbo-metrics-default/pom.xml | 6 +
.../pom.xml | 12 +-
.../collector/RegistryMetricsCollector.java | 123 +++++++++++
.../collector/stat/RegistryStatComposite.java | 240 +++++++++++++++++++++
.../registry/collector/stat/ServiceKeyMetric.java | 83 +++++++
.../registry/event/MetricsDirectoryListener.java | 43 ++++
.../registry/event/MetricsNotifyListener.java | 54 +++++
.../registry/event/MetricsRegisterListener.java | 52 +++++
.../registry/event/MetricsSubscribeListener.java | 52 +++++
.../metrics/registry/event/RegistryEvent.java | 156 ++++++++++++++
.../event/RegistryMetricsEventMulticaster.java} | 25 +--
...apache.dubbo.metrics.collector.MetricsCollector | 1 +
.../collector/RegistryMetricsCollectorTest.java | 115 ++++++++++
.../collector/RegistryMetricsSampleTest.java | 97 +++++++++
.../registry/metrics/model/MethodMetricTest.java | 79 +++++++
.../model/sample/GaugeMetricSampleTest.java | 63 ++++++
dubbo-metrics/pom.xml | 1 +
dubbo-registry/dubbo-registry-api/pom.xml | 7 +
.../listener/ServiceInstancesChangedListener.java | 48 +++--
.../registry/integration/RegistryDirectory.java | 39 ++--
dubbo-test/dubbo-dependencies-all/pom.xml | 5 +
38 files changed, 1385 insertions(+), 95 deletions(-)
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 @@
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metrics-registry</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
</project>
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,21 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster.directory;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.Semaphore;
-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;
@@ -42,6 +27,8 @@ 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;
@@ -54,6 +41,21 @@ 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;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
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<T> implements
Directory<T> {
*/
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<T> implements
Directory<T> {
}
// 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<T> implements
Directory<T> {
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<Invoker<T>> 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<Invoker<T>> availableInvokers;
@@ -381,6 +389,7 @@ public abstract class AbstractDirectory<T> implements
Directory<T> {
@Override
public void addDisabledInvoker(Invoker<T> 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<T> implements
Directory<T> {
@Override
public void recoverDisabledInvoker(Invoker<T> 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<T> implements
Directory<T> {
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<T> implements
Directory<T> {
}
private boolean addValidInvoker(Invoker<T> invoker) {
+ eventMulticaster.publishEvent(new
RegistryEvent.MetricsDirectoryEvent(applicationModel,
RegistryEvent.Type.D_VALID));
synchronized (this.validInvokers) {
return this.validInvokers.add(invoker);
}
}
private boolean removeValidInvoker(Invoker<T> 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<Invoker<String>> 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<String> 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<String, Object> 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 @@
<version>${project.parent.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metrics-api</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-default</artifactId>
<version>${project.parent.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metrics-registry</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-metadata</artifactId>
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
AbstractDeployer<ApplicationMode
private final AtomicInteger serviceRefreshState = new AtomicInteger(0);
private void registerServiceInstance() {
+ TimePair timePair = TimePair.start();
+ GlobalMetricsEventMulticaster eventMulticaster =
applicationModel.getBeanFactory().getBean(GlobalMetricsEventMulticaster.class);
+ eventMulticaster.publishEvent(new
RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
try {
registered = true;
ServiceInstanceMetadataUtils.registerMetadataAndInstance(applicationModel);
+ eventMulticaster.publishFinishEvent(new
RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
} catch (Exception e) {
+ eventMulticaster.publishErrorEvent(new
RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
logger.error(CONFIG_REGISTER_INSTANCE_ERROR, "configuration server
disconnected", "", "Register instance error.", e);
}
if (registered) {
diff --git a/dubbo-distribution/dubbo-all/pom.xml
b/dubbo-distribution/dubbo-all/pom.xml
index 49a224b69f..5e47b22074 100644
--- a/dubbo-distribution/dubbo-all/pom.xml
+++ b/dubbo-distribution/dubbo-all/pom.xml
@@ -190,6 +190,13 @@
<scope>compile</scope>
<optional>true</optional>
</dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metrics-registry</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ <optional>true</optional>
+ </dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-prometheus</artifactId>
@@ -502,6 +509,7 @@
<include>org.apache.dubbo:dubbo-metadata-report-zookeeper</include>
<include>org.apache.dubbo:dubbo-metrics-api</include>
<include>org.apache.dubbo:dubbo-metrics-default</include>
+
<include>org.apache.dubbo:dubbo-metrics-registry</include>
<include>org.apache.dubbo:dubbo-metrics-metadata</include>
<include>org.apache.dubbo:dubbo-metrics-prometheus</include>
<include>org.apache.dubbo:dubbo-monitor-api</include>
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 @@
<artifactId>dubbo-metrics-default</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metrics-registry</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-prometheus</artifactId>
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 @@
<artifactId>dubbo-common</artifactId>
<version>${project.parent.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-cluster</artifactId>
- <version>${project.parent.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-api</artifactId>
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<MetricsLifeListener> 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 @@
<artifactId>micrometer-tracing-integration-test</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-cluster</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/dubbo-metrics/dubbo-metrics-default/pom.xml
b/dubbo-metrics/dubbo-metrics-registry/pom.xml
similarity index 80%
copy from dubbo-metrics/dubbo-metrics-default/pom.xml
copy to dubbo-metrics/dubbo-metrics-registry/pom.xml
index 71be413c6a..86f190ff76 100644
--- a/dubbo-metrics/dubbo-metrics-default/pom.xml
+++ b/dubbo-metrics/dubbo-metrics-registry/pom.xml
@@ -23,7 +23,7 @@
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
- <artifactId>dubbo-metrics-default</artifactId>
+ <artifactId>dubbo-metrics-registry</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>The metrics module of dubbo project</description>
@@ -36,15 +36,5 @@
<artifactId>dubbo-metrics-api</artifactId>
<version>${project.parent.version}</version>
</dependency>
- <dependency>
- <groupId>io.micrometer</groupId>
- <artifactId>micrometer-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>io.micrometer</groupId>
- <artifactId>micrometer-tracing-integration-test</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
</project>
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<RegistryEvent.Type, RegistryEvent> {
+
+ 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<String, Integer> 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<MetricSample> collect() {
+ if (!isCollectEnabled()) {
+ new ArrayList<>();
+ }
+ List<MetricSample> 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<RegistryEvent.Type, Map<String, AtomicLong>> numStats = new
ConcurrentHashMap<>();
+ public Map<RegistryEvent.Type, Map<ServiceKeyMetric, AtomicLong>> skStats
= new ConcurrentHashMap<>();
+ public List<LongContainer<? extends Number>> 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<LongContainer<? extends Number>> initStats(String
registryOpType) {
+ List<LongContainer<? extends Number>> 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<GaugeMetricSample> exportNumMetrics() {
+ List<GaugeMetricSample> list = new ArrayList<>();
+ for (RegistryEvent.Type type : numStats.keySet()) {
+ Map<String, AtomicLong> stringAtomicLongMap = numStats.get(type);
+ for (String applicationName : stringAtomicLongMap.keySet()) {
+ list.add(convertToSample(applicationName, type,
MetricsCategory.REGISTRY, stringAtomicLongMap.get(applicationName)));
+ }
+ }
+ return list;
+ }
+
+ @Override
+ public List<GaugeMetricSample> exportRtMetrics() {
+ List<GaugeMetricSample> list = new ArrayList<>();
+ for (LongContainer<? extends Number> rtContainer : rtStats) {
+ MetricsKeyWrapper metricsKeyWrapper =
rtContainer.getMetricsKeyWrapper();
+ for (Map.Entry<String, ? extends Number> 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<GaugeMetricSample> exportSkMetrics() {
+ List<GaugeMetricSample> list = new ArrayList<>();
+ for (RegistryEvent.Type type : skStats.keySet()) {
+ Map<ServiceKeyMetric, AtomicLong> 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 <NUMBER>
+ */
+ public static class LongContainer<NUMBER extends Number> extends
ConcurrentHashMap<String, NUMBER> {
+
+ /**
+ * 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<String, NUMBER> initFunc;
+ /**
+ * Statistical data calculation function, which can be self-increment,
self-decrement, or more complex avg function
+ */
+ private final BiConsumer<Long, NUMBER> consumerFunc;
+ /**
+ * Data output function required by {@link GaugeMetricSample
GaugeMetricSample}
+ */
+ private Function<String, Long> valueSupplier;
+
+
+ public LongContainer(MetricsKeyWrapper metricsKeyWrapper,
Supplier<NUMBER> initFunc, BiConsumer<Long, NUMBER> 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<String, NUMBER> getInitFunc() {
+ return initFunc;
+ }
+
+ public BiConsumer<Long, NUMBER> getConsumerFunc() {
+ return consumerFunc;
+ }
+
+ public Function<String, Long> getValueSupplier() {
+ return valueSupplier;
+ }
+
+ public void setValueSupplier(Function<String, Long> valueSupplier) {
+ this.valueSupplier = valueSupplier;
+ }
+
+ @Override
+ public String toString() {
+ return "LongContainer{" +
+ "metricsKeyWrapper=" + metricsKeyWrapper +
+ '}';
+ }
+ }
+
+ public static class AtomicLongContainer extends LongContainer<AtomicLong> {
+
+ public AtomicLongContainer(MetricsKeyWrapper metricsKeyWrapper) {
+ super(metricsKeyWrapper, AtomicLong::new, (responseTime,
longAccumulator) -> longAccumulator.set(responseTime));
+ }
+
+ public AtomicLongContainer(MetricsKeyWrapper metricsKeyWrapper,
BiConsumer<Long, AtomicLong> consumerFunc) {
+ super(metricsKeyWrapper, AtomicLong::new, consumerFunc);
+ }
+
+ }
+
+ public static class LongAccumulatorContainer extends
LongContainer<LongAccumulator> {
+ 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<String, String> getTags() {
+ Map<String, String> 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<RegistryEvent.MetricsDirectoryEvent> {
+
+ @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<RegistryEvent.MetricsNotifyEvent> {
+
+ 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<RegistryEvent.MetricsRegisterEvent> {
+
+
+ @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<RegistryEvent.MetricsSubscribeEvent> {
+
+ @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<String, Integer> lastNumMap;
+
+ public MetricsNotifyEvent(ApplicationModel applicationModel, TimePair
timePair, Map<String, Integer> lastNumMap) {
+ super(applicationModel, timePair);
+ this.lastNumMap = lastNumMap;
+ }
+
+ public Map<String, Integer> 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-api/src/main/java/org/apache/dubbo/metrics/model/TimePair.java
b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryMetricsEventMulticaster.java
similarity index 61%
copy from
dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/TimePair.java
copy to
dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryMetricsEventMulticaster.java
index 3994fe9dd2..566607efdb 100644
---
a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/TimePair.java
+++
b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryMetricsEventMulticaster.java
@@ -15,26 +15,19 @@
* limitations under the License.
*/
-package org.apache.dubbo.metrics.model;
+package org.apache.dubbo.metrics.registry.event;
-public class TimePair {
+import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
- private final long begin;
- private long end;
+public final class RegistryMetricsEventMulticaster extends
SimpleMetricsEventMulticaster {
- public TimePair(long currentTimeMillis) {
- this.begin = currentTimeMillis;
- }
-
- public static TimePair start() {
- return new TimePair(System.currentTimeMillis());
- }
+ public RegistryMetricsEventMulticaster() {
+ super.addListener(new MetricsRegisterListener());
+ super.addListener(new MetricsSubscribeListener());
+ super.addListener(new MetricsNotifyListener());
+ super.addListener(new MetricsDirectoryListener());
- public void end() {
- this.end = System.currentTimeMillis();
+ setAvailable();
}
- public long calc() {
- return end - begin;
- }
}
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<MetricSample> 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<String, String> tags = sample.getTags();
+ Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME),
applicationModel.getApplicationName());
+ }
+ Map<String, Long> 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<MetricSample> samples = collector.collect();
+ for (MetricSample sample : samples) {
+ Map<String, String> tags = sample.getTags();
+ Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME),
applicationName);
+ }
+
+ Map<String, Long> 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<String, String> 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<String, String> tags;
+ private static MetricsCategory category;
+ private static String baseUnit;
+ private static Supplier<Number> 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 @@
<modules>
<module>dubbo-metrics-api</module>
<module>dubbo-metrics-default</module>
+ <module>dubbo-metrics-registry</module>
<module>dubbo-metrics-metadata</module>
<module>dubbo-metrics-prometheus</module>
</modules>
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 @@
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metrics-registry</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
</project>
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,25 +16,10 @@
*/
package org.apache.dubbo.registry.client.event.listener;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-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.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
@@ -43,6 +28,9 @@ 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;
@@ -54,6 +42,22 @@ import
org.apache.dubbo.registry.client.metadata.ServiceInstanceNotificationCust
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;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
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<ServiceInstanceNotificationCustomizer>
serviceInstanceNotificationCustomizers;
+ private final ApplicationModel applicationModel;
public ServiceInstancesChangedListener(Set<String> 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<String, Integer> 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<URL> 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<URL> toUrlsWithEmpty(List<URL> 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<T> extends
DynamicDirectory<T> {
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<T> extends
DynamicDirectory<T> {
// use local reference to avoid NPE as this.cachedInvokerUrls will
be set null by destroyAllInvokers().
Set<URL> 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 @@
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-default</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metrics-registry</artifactId>
+ </dependency>
+
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-metadata</artifactId>