Merge branch '3.3' into 3.3.0-beta.1-release

This commit is contained in:
chickenlj 2023-08-28 17:06:55 +08:00
commit 186ec674bf
152 changed files with 2964 additions and 1035 deletions

View File

@ -65,6 +65,7 @@ dubbo-metrics-metadata
dubbo-metrics-prometheus
dubbo-metrics-registry
dubbo-metrics-config-center
dubbo-metrics-netty
dubbo-monitor
dubbo-monitor-api
dubbo-monitor-common

View File

@ -25,6 +25,7 @@ notifications:
github:
homepage: https://dubbo.apache.org/
description: "The java implementation of Apache Dubbo. An RPC and microservice framework."
features:
# Enable wiki for documentation
wiki: true
@ -44,9 +45,13 @@ github:
foo: bar
labels:
- java
- rpc
- microservices
- framework
- restful
- distributed-systems
- rpc
- dubbo
- service-mesh
- http
- grpc
- web

View File

@ -184,7 +184,7 @@ check 2.7.5 milestone for details.
- Add a script to check dependencies license. [#3840](https://github.com/apache/dubbo/issues/3840)
- Change DynamicConfiguration definition to better adapt to Apollo's namespace storage model.[#3266](https://github.com/apache/dubbo/issues/3266)
- use equal explicit class to replace anonymous class [#4027](https://github.com/apache/dubbo/issues/4027)
- Seperate Constants.java into some SubConstants Class [#3137](https://github.com/apache/dubbo/issues/3137)
- Separate Constants.java into some SubConstants Class [#3137](https://github.com/apache/dubbo/issues/3137)
- Need to enhance DecodeableRpcResult error message [#3994](https://github.com/apache/dubbo/issues/3994)
- Provide more meaningful binary releases. [#2491](https://github.com/apache/dubbo/issues/2491)
- remove useless module-dubbo-test-integration [#3573](https://github.com/apache/dubbo/issues/3573)
@ -211,7 +211,7 @@ check 2.7.5 milestone for details.
- Fix consumer will generate wrong stackTrace. [#4137](https://github.com/apache/dubbo/issues/4137)
- nacos registry serviceName may conflict. [#4111](https://github.com/apache/dubbo/issues/4111)
- The client loses the listener when the network is reconnected. [#4115](https://github.com/apache/dubbo/issues/4115)
- fix registery urls increase forever when recreate reference proxy. [#4109](https://github.com/apache/dubbo/issues/4109)
- fix registry urls increase forever when recreate reference proxy. [#4109](https://github.com/apache/dubbo/issues/4109)
- In dubbo 2.7.1the watcher processor of zookeeper client throw Nullpointexception. [#3866](https://github.com/apache/dubbo/issues/3866)
- ReferenceConfig initialized not changed to false once subscribe throws exception [#4068](https://github.com/apache/dubbo/issues/4068)
- dubbo registry extension compatibility with dubbo 2.6.x. [#3882](https://github.com/apache/dubbo/issues/3882)
@ -400,7 +400,7 @@ Enhancement / New feature
* tag route. #3065
* Use Netty4 as default Netty version. #3029
* upporting Java 8 Date/Time type when serializing with Kryo #3519
* supoort config telnet #3511
* support config telnet #3511
* add annotation driven in MethodConfig and ArgumentConfig #2603
* add nacos-registry module #3296
* add `protocol` attribute in `@Rerefence` #3555
@ -416,7 +416,7 @@ BugFix
* SPI entires dup by 3 times #3315
* fix Consumer throws RpcException after RegistryDirectory notify in high QPS #2016
* fix NPE in @Reference when using Junit to test dubbo service #3429
* fix consuer always catch java.lang.reflect.UndeclaredThrowableException for any exception throws in provider #3386
* fix consumer always catch java.lang.reflect.UndeclaredThrowableException for any exception throws in provider #3386
* fix the priority of `DubboConfigConfigurationSelector ` #2897
* fix `@Rerefence#parameters()` not work #2301

View File

@ -1,21 +1,8 @@
## What is the purpose of the change
## What is the purpose of the change?
## Brief changelog
## Verifying this change
<!-- Follow this checklist to help us incorporate your contribution quickly and easily: -->
## Checklist
- [x] Make sure there is a [GitHub_issue](https://github.com/apache/dubbo/issues) field for the change (usually before you start working on it). Trivial changes like typos do not require a GitHub issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
- [ ] Each commit in the pull request should have a meaningful subject line and body.
- [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
- [ ] Check if is necessary to patch to Dubbo 3 if you are work on Dubbo 2.7
- [ ] Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add sample in [dubbo samples](https://github.com/apache/dubbo-samples) project.
- [ ] Add some description to [dubbo-website](https://github.com/apache/dubbo-website) project if you are requesting to add a feature.
- [ ] GitHub Actions works fine on your own branch.
- [ ] If this contribution is large, please follow the [Software Donation Guide](https://github.com/apache/dubbo/wiki/Software-donation-guide).
- [x] Make sure there is a [GitHub_issue](https://github.com/apache/dubbo/issues) field for the change.
- [x] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
- [x] Write necessary unit-test to verify your logic correction. If the new feature or significant change is committed, please remember to add sample in [dubbo samples](https://github.com/apache/dubbo-samples) project.
- [x] Make sure gitHub actions can pass. [Why the workflow is failing and how to fix it?](./CONTRIBUTING.md)

255
README.md
View File

@ -10,236 +10,69 @@
[![Twitter Follow](https://img.shields.io/twitter/follow/ApacheDubbo.svg?label=Follow&style=social&logoWidth=0)](https://twitter.com/intent/follow?screen_name=ApacheDubbo)
[![Gitter](https://badges.gitter.im/alibaba/dubbo.svg)](https://gitter.im/alibaba/dubbo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
Apache Dubbo is a high-performance, Java-based open-source RPC framework. Please visit the [official site](http://dubbo.apache.org) for the quick start guide and documentation, as well as the [wiki](https://github.com/apache/dubbo/wiki) for news, FAQ, and release notes.
Apache Dubbo is an easy-to-use Web and RPC framework that provides multiple
language implementations(Java, [Go](https://github.com/apache/dubbo-go), [Rust](https://github.com/apache/dubbo-rust), [Node.js](https://github.com/apache/dubbo-js), [Web](https://github.com/apache/dubbo-js)) for communication, service discovery, traffic management,
observability, security, tools, and best practices for building enterprise-ready microservices.
We are now collecting Dubbo user info to help us to improve Dubbo further. Kindly support us by providing your usage information on [issue#9436: Wanted: who's using dubbo](https://github.com/apache/dubbo/issues/9436), thanks :)
Visit [the official website](https://dubbo.apache.org/) for more information.
## Architecture
![Architecture](https://dubbo.apache.org/imgs/architecture.png)
## Features
* Transparent interface based RPC
* Intelligent load balancing
* Automatic service registration and discovery
* High extensibility
* Runtime traffic routing
* Visualized service governance
* Consumer and provider communicate with each other using RPC protocol like triple, tcp, rest, etc.
* Consumers automatically trace provider instances registered in registries(Zookeeper, Nacos) and distribute traffic among them by following traffic strategies.
* Rich features for monitoring and managing the cluster with dynamic configuration, metrics, tracing, security, and visualized console.
## Getting started
Follow the instructions below to learn how to:
The following code snippet comes from [Dubbo Samples](https://github.com/apache/dubbo-samples.git). You may clone the sample project and step into the `dubbo-samples-api` subdirectory before proceeding.
### Programming with lightweight RPC API
[5 minutes step-by-step guide](https://dubbo.apache.org/zh-cn/overview/quickstart/rpc/java)
```bash
git clone https://github.com/apache/dubbo-samples.git
cd dubbo-samples/1-basic/dubbo-samples-api
```
There's a [README](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/README.md) file under `dubbo-samples-api` directory. We recommend referencing the samples in that directory by following the below-mentioned instructions:
### Maven dependency
```xml
<properties>
<dubbo.version>3.0.10</dubbo.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
</dependency>
</dependencies>
```
### Define service interfaces
```java
package org.apache.dubbo.samples.api;
public interface GreetingsService {
String sayHi(String name);
}
```
*See [api/GreetingsService.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java) on GitHub.*
### Implement service interface for the provider
```java
package org.apache.dubbo.samples.provider;
import org.apache.dubbo.samples.api.GreetingsService;
public class GreetingsServiceImpl implements GreetingsService {
@Override
public String sayHi(String name) {
return "hi, " + name;
}
}
```
*See [provider/GreetingsServiceImpl.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java) on GitHub.*
### Start service provider
```java
package org.apache.dubbo.samples.provider;
Dubbo supports building RPC services with only a few lines of code while depending only on a lightweight SDK (<10MB). The protocol on the wire can be [Triple](https://dubbo.apache.org/zh-cn/overview/reference/protocols/triple/)(fully gRPC compatible and HTTP-friendly), Dubbo2(TCP), REST, or any protocol of your choice.
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.samples.api.GreetingsService;
### Building a microservice application with Spring Boot
[5 minutes step-by-step guide](https://dubbo.apache.org/zh-cn/overview/quickstart/microservice)
import java.util.concurrent.CountDownLatch;
It's highly recommended to start your microservice application with the Spring Boot Starter `dubbo-spring-boot-starter` provided by Dubbo. With only a single dependency and yaml file, and optionally a bunch of other useful spring boot starters, you can enable all of the Dubo features like service discovery, observability, tracing, etc.
public class Application {
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
Next, learn how to [deploy](https://dubbo.apache.org/zh-cn/overview/tasks/deploy/), [monitor](https://dubbo.apache.org/zh-cn/overview/tasks/observability/), and [manage the traffic](https://dubbo.apache.org/zh-cn/overview/tasks/traffic-management/) of your Dubbo application and cluster.
public static void main(String[] args) throws Exception {
ServiceConfig<GreetingsService> service = new ServiceConfig<>();
service.setApplication(new ApplicationConfig("first-dubbo-provider"));
service.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
service.setInterface(GreetingsService.class);
service.setRef(new GreetingsServiceImpl());
service.export();
## More Features
Get more details by visiting the links below to get your hands dirty with some well-designed tasks on our website.
System.out.println("dubbo service started");
new CountDownLatch(1).await();
}
}
```
* [Launch a Dubbo project](https://dubbo.apache.org/zh-cn/overview/tasks/develop/template/)
* [RPC protocols](https://dubbo.apache.org/zh-cn/overview/core-features/protocols/)
* [Traffic management](https://dubbo.apache.org/zh-cn/overview/core-features/traffic/)
* [Service discovery](https://dubbo.apache.org/zh-cn/overview/core-features/service-discovery/)
* [Observability](https://dubbo.apache.org/zh-cn/overview/core-features/observability/)
* [Extensibility](https://dubbo.apache.org/zh-cn/overview/core-features/extensibility/)
* [Security](https://dubbo.apache.org/zh-cn/overview/core-features/security/)
* [Visualized console and control plane](https://dubbo.apache.org/zh-cn/overview/reference/admin/)
* [Kubernetes and Service mesh](https://dubbo.apache.org/zh-cn/overview/core-features/service-mesh/)
*See [provider/Application.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-spring-xml/src/main/java/org/apache/dubbo/samples/provider/Application.java) on GitHub.*
## Which Dubbo version should I use?
| **Dubbo3** | **JDK** | **Dependencies** | **Description** |
| --- | --- | --- | --- |
| 3.3.0-beta| 1.8 17 | [dependency list](https://github.com/apache/dubbo/blob/3.3/dubbo-dependencies-bom/pom.xml#L94) | **- Unstable version** <br/> **- Features** <br/> &nbsp;&nbsp; - Triple - gRPC and cURL compatible.<br/> &nbsp;&nbsp; - Rest-style programming support.<br/> &nbsp;&nbsp; - Spring Boot Starters. |
| 3.2.5 | 1.8 17 | [dependency list](https://github.com/apache/dubbo/blob/dubbo-3.2.5/dubbo-dependencies-bom/pom.xml#L94) | **- Stable version (active)** <br/> **- Features** <br/> &nbsp;&nbsp;- Out-of-box metrics and tracing support.<br/> &nbsp;&nbsp;- Threadpool Isolation<br/> &nbsp;&nbsp;- 30% performance<br/> &nbsp;&nbsp;- Native Image|
| 3.1.11 | 1.8 11 | [dependency list](https://github.com/apache/dubbo/blob/dubbo-3.2.11/dubbo-dependencies-bom/pom.xml#L94) | **Stable version (not active)** |
### Build and run the provider
```bash
mvn clean package
mvn -Djava.net.preferIPv4Stack=true -Dexec.mainClass=org.apache.dubbo.samples.provider.Application exec:java
```
### Call remote service in the consumer
```java
package org.apache.dubbo.samples.client;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.samples.api.GreetingsService;
public class Application {
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
public static void main(String[] args) {
ReferenceConfig<GreetingsService> reference = new ReferenceConfig<>();
reference.setApplication(new ApplicationConfig("first-dubbo-consumer"));
reference.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
reference.setInterface(GreetingsService.class);
GreetingsService service = reference.get();
String message = service.sayHi("dubbo");
System.out.println(message);
}
}
```
*See [client/Application.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java) on GitHub.*
### Build and run the consumer
```bash
mvn clean package
mvn -Djava.net.preferIPv4Stack=true -Dexec.mainClass=org.apache.dubbo.samples.client.Application exec:java
```
The consumer will print out `hi, dubbo` on the screen.
### Next steps
* [Your first Dubbo application](https://dubbo.apache.org/en/blog/2018/08/07/dubbo-101/) - A 101 tutorial to reveal more details, with the same code above.
* [Dubbo user manual](https://dubbo.apache.org/en/overview/what/) - How to use Dubbo and all its features.
* [Dubbo developer guide](https://dubbo.apache.org/en/docs3-v2/java-sdk/) - How to involve in Dubbo development.
* [Dubbo admin manual](https://dubbo.apache.org/en/docs/v2.7/admin/ops/) - How to admin and manage Dubbo services.
## Building
If you want to try out the cutting-edge features, you can build with the following commands. (Java 1.8 is needed to build the master branch)
```
mvn clean install
```
## Recommended Test Environment
To avoid intermittent test failures (i.e., flaky tests), it is recommended to have a machine or virtual machine with the following specifications:
* Minumum of 2CPUs.
* Minimum of 2Gb of RAM.
## Contact
* Mailing list:
* dev list: for dev/user discussion. [subscribe](mailto:dev-subscribe@dubbo.apache.org), [unsubscribe](mailto:dev-unsubscribe@dubbo.apache.org), [archive](https://lists.apache.org/list.html?dev@dubbo.apache.org), [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide)
* Bugs: [Issues](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md)
* Gitter: [Gitter channel](https://gitter.im/alibaba/dubbo)
* Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
| **Dubbo2** | **JDK** | **Dependencies** | **Description** |
| --- | --- | --- | --- |
| 2.7.23 | 1.8 | [dependency list](https://github.com/apache/dubbo/blob/dubbo-2.7.23/dubbo-dependencies-bom/pom.xml#L92) | EOL |
| 2.6.x, 2.5.x | 1.6 1.7 | | EOL |
## Contributing
See [CONTRIBUTING](https://github.com/apache/dubbo/blob/master/CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
See [CONTRIBUTING](https://github.com/apache/dubbo/blob/master/CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
### How can I contribute?
* Take a look at issues with tags marked [`Good first issue`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) or [`Help wanted`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).
* Join the discussion on the mailing list, subscription [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide).
* Answer questions on [issues](https://github.com/apache/dubbo/issues).
* Fix bugs reported on [issues](https://github.com/apache/dubbo/issues), and send us a pull request.
* Review the existing [pull request](https://github.com/apache/dubbo/pulls).
* Improve the [website](https://github.com/apache/dubbo-website), typically we need
* blog post
* translation on documentation
* use cases around the integration of Dubbo in enterprise systems.
* Improve the [dubbo-admin/dubbo-monitor](https://github.com/apache/dubbo-admin).
* Contribute to the projects listed in [ecosystem](https://github.com/dubbo).
* Other forms of contribution not explicitly enumerated above.
* If you would like to contribute, please send an email to dev@dubbo.apache.org to let us know!
## Reporting bugs
Please follow the [template](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md) for reporting any issues.
## Reporting a security vulnerability
Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org) privately.
## Dubbo ecosystem
* [Dubbo Ecosystem Entry](https://github.com/apache?utf8=%E2%9C%93&q=dubbo&type=&language=) - A GitHub group `dubbo` to gather all Dubbo relevant projects not appropriate in [apache](https://github.com/apache) group yet
* [Dubbo Website](https://github.com/apache/dubbo-website) - Apache Dubbo official website
* [Dubbo Samples](https://github.com/apache/dubbo-samples) - samples for Apache Dubbo
* [Dubbo Spring Boot](https://github.com/apache/dubbo-spring-boot-project) - Spring Boot Project for Dubbo
* [Dubbo Admin](https://github.com/apache/dubbo-admin) - The reference implementation for Dubbo admin
* [Dubbo Awesome](https://github.com/apache/dubbo-awesome) - Dubbo's slides and video links in Meetup
#### Language
* [Go](https://github.com/dubbo/dubbo-go) (recommended)
* [Node.js](https://github.com/apache/dubbo-js)
* [Python](https://github.com/dubbo/py-client-for-apache-dubbo)
* [PHP](https://github.com/apache/dubbo-php-framework)
* [Erlang](https://github.com/apache/dubbo-erlang)
## Contact
* WeChat: apachedubbo
* DingTalk group: 37290003945
* Mailing list: [guide](https://dubbo.apache.org/zh-cn/contact/)
* Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
* Security issues: please mail to [us](mailto:security@dubbo.apache.org) privately.
## License
Apache Dubbo software is licenced under the Apache License Version 2.0. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.
Apache Dubbo is licensed under the Apache License Version 2.0. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.

View File

@ -352,7 +352,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
}
}, reconnectTaskPeriod, TimeUnit.MILLISECONDS);
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary()));
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
/**
@ -366,7 +366,11 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
if (invokersInitialized) {
refreshInvokerInternal();
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary()));
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
protected Map<String, String> getDirectoryMeta() {
return Collections.emptyMap();
}
private synchronized void refreshInvokerInternal() {
@ -395,7 +399,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
removeValidInvoker(invoker);
logger.info("Disable service address: " + invoker.getUrl() + ".");
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary()));
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
@Override
@ -408,7 +412,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
}
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary()));
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
protected final void refreshRouter(BitList<Invoker<T>> newlyInvokers, Runnable switchAction) {
@ -465,7 +469,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
refreshInvokerInternal();
this.invokersInitialized = true;
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary()));
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
protected void destroyInvokers() {
@ -480,7 +484,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
synchronized (this.validInvokers) {
result = this.validInvokers.add(invoker);
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary()));
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
return result;
}
@ -489,7 +493,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
synchronized (this.validInvokers) {
result = this.validInvokers.remove(invoker);
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary()));
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
return result;
}
@ -519,18 +523,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
}
private Map<String, Integer> groupByServiceKey(Collection<Invoker<T>> invokers) {
Map<String, Integer> serviceNumMap = new HashMap<>();
for (Invoker<T> invoker : invokers) {
if (invoker.getClass().getSimpleName().contains("Mockito")) {
return serviceNumMap;
}
}
if (invokers.size() > 0) {
serviceNumMap = invokers.stream().filter(invoker -> invoker.getInterface() != null).collect(Collectors.groupingBy(invoker -> invoker.getInterface().getName(), Collectors.reducing(0, e -> 1, Integer::sum)));
}
return serviceNumMap;
return Collections.singletonMap(getConsumerUrl().getServiceKey(), invokers.size());
}
@Override

View File

@ -27,9 +27,12 @@ import org.apache.dubbo.rpc.cluster.RouterChain;
import org.apache.dubbo.rpc.cluster.SingleRouterChain;
import org.apache.dubbo.rpc.cluster.router.state.BitList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_SITE_SELECTION;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
/**
* StaticDirectory
@ -125,4 +128,8 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
return invokers;
}
@Override
protected Map<String, String> getDirectoryMeta() {
return Collections.singletonMap(REGISTRY_KEY, "static");
}
}

View File

@ -33,6 +33,8 @@ public interface CommonConstants {
String CONSUMER = "consumer";
String CALLBACK = "callback";
String APPLICATION_KEY = "application";
String APPLICATION_VERSION_KEY = "application.version";
@ -241,6 +243,8 @@ public interface CommonConstants {
String INTERFACE_REGISTER_MODE = "interface";
String INSTANCE_REGISTER_MODE = "instance";
String DEFAULT_REGISTER_MODE = "all";
String GENERIC_KEY = "generic";
@ -637,8 +641,7 @@ public interface CommonConstants {
String REST_SERVICE_DEPLOYER_URL_ATTRIBUTE_KEY = "restServiceDeployerAttributeKey";
String SERVICE_DEPLOYER_ATTRIBUTE_KEY = "serviceDeployer";
String RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY = "resteasyNettyHttpRequest";
String SERVICE_DEPLOYER_ATTRIBUTE_KEY = "serviceDeployer"; String RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY = "resteasyNettyHttpRequest";
String DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register";
}

View File

@ -47,6 +47,8 @@ public interface MetricsConstants {
String TAG_CHANGE_TYPE = "change.type";
String TAG_ERROR_CODE = "error";
String ENABLE_JVM_METRICS_KEY = "enable.jvm";
String AGGREGATION_COLLECTOR_KEY = "aggregation";

View File

@ -14,24 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.tracing.exporter;
import brave.handler.SpanHandler;
import io.opentelemetry.sdk.trace.export.SpanExporter;
package org.apache.dubbo.common.logger;
public interface TraceExporter {
/**
* Loggers that can register to listen to log messages.
*/
public interface ListenableLogger extends ErrorTypeAwareLogger{
/**
* for otel
* Register a listener to this loggerand get notified when a log happens.
*
* @return
* @param listener log listener
*/
SpanExporter getSpanExporter();
void registerListen(LogListener listener);
/**
* for brave
*
* @return
*/
SpanHandler getSpanHandler();
}

View File

@ -0,0 +1,27 @@
/*
* 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.common.logger;
/**
* Log Listener, can registered to an {@link ListenableLogger}.
*/
public interface LogListener {
void onMessage(String code, String msg);
}

View File

@ -18,16 +18,22 @@
package org.apache.dubbo.common.logger.support;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.ListenableLogger;
import org.apache.dubbo.common.logger.LogListener;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.utils.NetUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
/**
* A fail-safe (ignoring exception thrown by logger) wrapper of error type aware logger.
*/
public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements ErrorTypeAwareLogger {
public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements ListenableLogger {
/**
* Template address for formatting.
@ -36,6 +42,16 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
private static final Pattern ERROR_CODE_PATTERN = Pattern.compile("\\d+-\\d+");
/**
* Listeners that listened to all Loggers.
*/
private static final List<LogListener> GLOBAL_LISTENERS = Collections.synchronizedList(new ArrayList<>());
/**
* Listeners that listened to this listener.
*/
private final AtomicReference<List<LogListener>> listeners = new AtomicReference<>();
public FailsafeErrorTypeAwareLogger(Logger logger) {
super(logger);
}
@ -80,6 +96,7 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
}
try {
onEvent(code, msg);
getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg));
} catch (Throwable t) {
// ignored.
@ -93,6 +110,7 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
}
try {
onEvent(code, msg);
getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg), e);
} catch (Throwable t) {
// ignored.
@ -106,6 +124,7 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
}
try {
onEvent(code, msg);
getLogger().error(appendContextMessageWithInstructions(code, cause, extendedInformation, msg));
} catch (Throwable t) {
// ignored.
@ -119,9 +138,45 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
}
try {
onEvent(code, msg);
getLogger().error(appendContextMessageWithInstructions(code, cause, extendedInformation, msg), e);
} catch (Throwable t) {
// ignored.
}
}
public static void registerGlobalListen(LogListener listener) {
GLOBAL_LISTENERS.add(listener);
}
@Override
public void registerListen(LogListener listener) {
listeners.getAndUpdate(logListeners -> {
if (logListeners == null) {
logListeners = Collections.synchronizedList(new ArrayList<>());
}
logListeners.add(listener);
return logListeners;
});
}
private void onEvent(String code, String msg) {
Optional.ofNullable(listeners.get()).ifPresent(
logListeners -> logListeners.forEach(logListener -> {
try {
logListener.onMessage(code, msg);
} catch (Exception e) {
// ignored.
}
}));
GLOBAL_LISTENERS.forEach(logListener -> {
try {
logListener.onMessage(code, msg);
} catch (Exception e) {
// ignored.
}
});
}
}

View File

@ -159,7 +159,7 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
"Current mode is `WARN`, will disallow to deserialize it by default. " +
"Please add it into security/serialize.allowlist or follow FAQ to configure it.";
if (serializeSecurityManager.getWarnedClasses().add(className)) {
logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg);
logger.warn(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg);
}
throw new IllegalArgumentException(msg);
@ -180,7 +180,7 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
"Current mode is `WARN`, will disallow to deserialize it by default. " +
"Please add it into security/serialize.allowlist or follow FAQ to configure it.";
if (serializeSecurityManager.getWarnedClasses().add(className)) {
logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg);
logger.warn(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg);
}
throw new IllegalArgumentException(msg);
@ -189,7 +189,7 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
Class<?> clazz = ClassUtils.forName(className, classLoader);
if (serializeSecurityManager.getWarnedClasses().add(className)) {
logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "",
logger.warn(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "",
"[Serialization Security] Serialized class " + className + " is not in allow list. " +
"Current mode is `WARN`, will allow to deserialize it by default. " +
"Dubbo will set to `STRICT` mode by default in the future. " +

View File

@ -856,6 +856,23 @@ public final class StringUtils {
return sb.toString();
}
public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) {
if (ArrayUtils.isEmpty(array)) {
return EMPTY_STRING;
}
if (endIndex - startIndex <= 0) {
return EMPTY_STRING;
}
StringBuilder sb = new StringBuilder();
for (int i = startIndex; i < endIndex; i++) {
if (i > 0) {
sb.append(delimiter);
}
sb.append(array[i]);
}
return sb.toString();
}
/**
* parse key-value pair.
*

View File

@ -61,6 +61,11 @@ public class MetricsConfig extends AbstractConfig {
*/
private Boolean exportMetricsService;
/**
* Enable netty metrics.
*/
private Boolean enableNetty;
/**
* @deprecated After metrics config is refactored.
* This parameter should no longer use and will be deleted in the future.
@ -223,4 +228,12 @@ public class MetricsConfig extends AbstractConfig {
public void setEnableRpc(Boolean enableRpc) {
this.enableRpc = enableRpc;
}
public Boolean getEnableNetty() {
return enableNetty;
}
public void setEnableNetty(Boolean enableNetty) {
this.enableNetty = enableNetty;
}
}

View File

@ -24,4 +24,6 @@ public interface ModelConstants {
* Keep Dubbo running when spring is stopped
*/
String KEEP_RUNNING_ON_SPRING_CLOSED = "keepRunningOnSpringClosed";
String KEEP_RUNNING_ON_SPRING_CLOSED_KEY = "dubbo.module.keepRunningOnSpringClosed";
}

View File

@ -227,6 +227,10 @@ class StringUtilsTest {
assertEquals(StringUtils.join(s), "123");
assertEquals(StringUtils.join(s, ','), "1,2,3");
assertEquals(StringUtils.join(s, ","), "1,2,3");
assertEquals(StringUtils.join(s, ',', 0, 1), "1");
assertEquals(StringUtils.join(s, ',', 0, 2), "1,2");
assertEquals(StringUtils.join(s, ',', 0, 3), "1,2,3");
assertEquals("", StringUtils.join(s, ',', 2, 0), "1,2");
}
@Test
@ -502,4 +506,4 @@ class StringUtilsTest {
assertTrue(startsWithIgnoreCase("Dubbo.application.name", "dubbo.application."));
}
}
}

View File

@ -463,7 +463,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
if (logger.isInfoEnabled()) {
logger.info("Referred dubbo service: [" + referenceParameters.get(INTERFACE_KEY) + "]." +
(Boolean.parseBoolean(referenceParameters.get(GENERIC_KEY)) ?
(ProtocolUtils.isGeneric(referenceParameters.get(GENERIC_KEY)) ?
" it's GenericService reference" : " it's not GenericService reference"));
}

View File

@ -38,8 +38,6 @@ import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.metadata.ServiceNameMapping;
import org.apache.dubbo.metrics.event.MetricsEventBus;
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
import org.apache.dubbo.registry.client.metadata.MetadataUtils;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;
@ -193,7 +191,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
}
@Override
public void unexport() {
public synchronized void unexport() {
if (!exported) {
return;
}
@ -517,21 +515,17 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
List<URL> registryURLs = !Boolean.FALSE.equals(isRegister()) ?
ConfigValidationUtils.loadRegistries(this, true) : Collections.emptyList();
MetricsEventBus.post(RegistryEvent.toRsEvent(getApplicationModel(), getUniqueServiceName(), protocols.size() * registryURLs.size()), () -> {
for (ProtocolConfig protocolConfig : protocols) {
String pathKey = URL.buildKey(getContextPath(protocolConfig)
.map(p -> p + "/" + path)
.orElse(path), group, version);
// stub service will use generated service name
if (!serverService) {
// In case user specified path, registerImmediately service one more time to map it to path.
repository.registerService(pathKey, interfaceClass);
}
doExportUrlsFor1Protocol(protocolConfig, registryURLs, registerType);
}
return null;
for (ProtocolConfig protocolConfig : protocols) {
String pathKey = URL.buildKey(getContextPath(protocolConfig)
.map(p -> p + "/" + path)
.orElse(path), group, version);
// stub service will use generated service name
if (!serverService) {
// In case user specified path, register service one more time to map it to path.
repository.registerService(pathKey, interfaceClass);
}
);
doExportUrlsFor1Protocol(protocolConfig, registryURLs, registerType);
}
providerModel.setServiceUrls(urls);
}

View File

@ -55,7 +55,6 @@ import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.config.event.ConfigCenterEvent;
import org.apache.dubbo.metrics.event.MetricsEventBus;
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
import org.apache.dubbo.metrics.report.DefaultMetricsReporterFactory;
import org.apache.dubbo.metrics.report.MetricsReporter;
import org.apache.dubbo.metrics.report.MetricsReporterFactory;
@ -914,16 +913,12 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
private void registerServiceInstance() {
try {
registered = true;
MetricsEventBus.post(RegistryEvent.toRegisterEvent(applicationModel),
() -> {
ServiceInstanceMetadataUtils.registerMetadataAndInstance(applicationModel);
return null;
}
);
} catch (Exception e) {
logger.error(CONFIG_REGISTER_INSTANCE_ERROR, "configuration server disconnected", "", "Register instance error.", e);
}
if (registered) {
// scheduled task for updating Metadata and ServiceInstance
asyncMetadataFuture = frameworkExecutorRepository.getSharedScheduledExecutor().scheduleWithFixedDelay(() -> {

View File

@ -335,6 +335,13 @@ public class DefaultModuleDeployer extends AbstractDeployer<ModuleModel> impleme
private void onModuleFailed(String msg, Throwable ex) {
try {
try {
// un-export all services if start failure
unexportServices();
} catch (Throwable t) {
logger.info("Failed to un-export services after module failed.", t);
}
setFailed(ex);
logger.error(CONFIG_FAILED_START_MODEL, "", "", "Model start failed: " + msg, ex);
applicationDeployer.notifyModuleChanged(moduleModel, DeployState.FAILED);
@ -450,8 +457,8 @@ public class DefaultModuleDeployer extends AbstractDeployer<ModuleModel> impleme
try {
configManager.removeConfig(sc);
sc.unexport();
} catch (Exception ignored) {
// ignored
} catch (Throwable t) {
logger.info("Failed to un-export service. Service Key: " + sc.getUniqueServiceName(), t);
}
});
exportedServices.clear();

View File

@ -73,7 +73,7 @@
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
<version>1.9.20</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -16,6 +16,7 @@
*/
package org.apache.dubbo.config.spring.context;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.deploy.DeployListenerAdapter;
import org.apache.dubbo.common.deploy.DeployState;
import org.apache.dubbo.common.deploy.ModuleDeployer;
@ -169,6 +170,9 @@ public class DubboDeployApplicationListener implements ApplicationListener<Appli
private void onContextClosedEvent(ContextClosedEvent event) {
try {
Object value = moduleModel.getAttribute(ModelConstants.KEEP_RUNNING_ON_SPRING_CLOSED);
if (value == null) {
value = ConfigurationUtils.getProperty(moduleModel, ModelConstants.KEEP_RUNNING_ON_SPRING_CLOSED_KEY);
}
boolean keepRunningOnClosed = Boolean.parseBoolean(String.valueOf(value));
if (!keepRunningOnClosed && !moduleModel.isDestroyed()) {
moduleModel.destroy();
@ -182,7 +186,7 @@ public class DubboDeployApplicationListener implements ApplicationListener<Appli
@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
return LOWEST_PRECEDENCE;
}
}

View File

@ -25,6 +25,7 @@ import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
@ -49,14 +50,14 @@ public class DubboSpringInitializer {
public static void initialize(BeanDefinitionRegistry registry) {
// prepare context and do customize
DubboSpringInitContext context = new DubboSpringInitContext();
// Spring ApplicationContext may not ready at this moment (e.g. load from xml), so use registry as key
if (contextMap.putIfAbsent(registry, new DubboSpringInitContext()) != null) {
if (contextMap.putIfAbsent(registry, context) != null) {
return;
}
// prepare context and do customize
DubboSpringInitContext context = contextMap.get(registry);
// find beanFactory
ConfigurableListableBeanFactory beanFactory = findBeanFactory(registry);
@ -69,11 +70,12 @@ public class DubboSpringInitializer {
}
public static boolean remove(ApplicationContext springContext) {
AutowireCapableBeanFactory autowireCapableBeanFactory = springContext.getAutowireCapableBeanFactory();
for (Map.Entry<BeanDefinitionRegistry, DubboSpringInitContext> entry : contextMap.entrySet()) {
DubboSpringInitContext initContext = entry.getValue();
if (initContext.getApplicationContext() == springContext ||
initContext.getBeanFactory() == springContext.getAutowireCapableBeanFactory() ||
initContext.getRegistry() == springContext.getAutowireCapableBeanFactory()
initContext.getBeanFactory() == autowireCapableBeanFactory ||
initContext.getRegistry() == autowireCapableBeanFactory
) {
DubboSpringInitContext context = contextMap.remove(entry.getKey());
logger.info("Unbind " + safeGetModelDesc(context.getModuleModel()) + " from spring container: " +
@ -89,8 +91,7 @@ public class DubboSpringInitializer {
}
static DubboSpringInitContext findBySpringContext(ApplicationContext applicationContext) {
for (Map.Entry<BeanDefinitionRegistry, DubboSpringInitContext> entry : contextMap.entrySet()) {
DubboSpringInitContext initContext = entry.getValue();
for (DubboSpringInitContext initContext : contextMap.values()) {
if (initContext.getApplicationContext() == applicationContext) {
return initContext;
}
@ -113,25 +114,26 @@ public class DubboSpringInitializer {
if (findContextForApplication(ApplicationModel.defaultModel()) == null) {
// first spring context use default application instance
applicationModel = ApplicationModel.defaultModel();
logger.info("Use default application: " + safeGetModelDesc(applicationModel));
logger.info("Use default application: " + applicationModel.getDesc());
} else {
// create a new application instance for later spring context
applicationModel = FrameworkModel.defaultModel().newApplication();
logger.info("Create new application: " + safeGetModelDesc(applicationModel));
logger.info("Create new application: " + applicationModel.getDesc());
}
// init ModuleModel
moduleModel = applicationModel.getDefaultModule();
context.setModuleModel(moduleModel);
logger.info("Use default module model of target application: " + safeGetModelDesc(moduleModel));
logger.info("Use default module model of target application: " + moduleModel.getDesc());
} else {
logger.info("Use module model from customizer: " + safeGetModelDesc(moduleModel));
logger.info("Use module model from customizer: " + moduleModel.getDesc());
}
logger.info("Bind " + safeGetModelDesc(moduleModel) + " to spring container: " + ObjectUtils.identityToString(registry));
logger.info("Bind " + moduleModel.getDesc() + " to spring container: " + ObjectUtils.identityToString(registry));
// set module attributes
if (context.getModuleAttributes().size() > 0) {
context.getModuleModel().getAttributes().putAll(context.getModuleAttributes());
Map<String, Object> moduleAttributes = context.getModuleAttributes();
if (moduleAttributes.size() > 0) {
moduleModel.getAttributes().putAll(moduleAttributes);
}
// bind dubbo initialization context to spring context
@ -207,7 +209,6 @@ public class DubboSpringInitializer {
customizer.customize(context);
}
customizerHolder.clearCustomizers();
}
}

View File

@ -1092,6 +1092,12 @@
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="enable-netty" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[ Enable netty metrics when collecting. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="export-metrics-service" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[ Enable export metrics service. ]]></xsd:documentation>

View File

@ -224,7 +224,7 @@
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.9.23</version>
<version>0.9.24</version>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<metadataRepository>

View File

@ -222,7 +222,7 @@
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.9.23</version>
<version>0.9.24</version>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<metadataRepository>

View File

@ -38,7 +38,7 @@
<skip_maven_deploy>true</skip_maven_deploy>
<spring-boot.version>2.7.14</spring-boot.version>
<spring-boot-maven-plugin.version>2.7.14</spring-boot-maven-plugin.version>
<micrometer-core.version>1.11.2</micrometer-core.version>
<micrometer-core.version>1.11.3</micrometer-core.version>
</properties>
<dependencyManagement>
<dependencies>

View File

@ -94,7 +94,7 @@
<spring_version>5.3.25</spring_version>
<spring_security_version>5.8.5</spring_security_version>
<javassist_version>3.29.2-GA</javassist_version>
<bytebuddy.version>1.14.5</bytebuddy.version>
<bytebuddy.version>1.14.6</bytebuddy.version>
<netty_version>3.2.10.Final</netty_version>
<netty4_version>4.1.95.Final</netty4_version>
<mina_version>2.2.1</mina_version>
@ -102,7 +102,7 @@
<httpclient_version>4.5.14</httpclient_version>
<httpcore_version>4.4.16</httpcore_version>
<fastjson_version>1.2.83</fastjson_version>
<fastjson2_version>2.0.35</fastjson2_version>
<fastjson2_version>2.0.39</fastjson2_version>
<zookeeper_version>3.4.14</zookeeper_version>
<curator_version>4.3.0</curator_version>
<curator_test_version>2.12.0</curator_test_version>
@ -114,7 +114,7 @@
<cxf_version>3.5.5</cxf_version>
<thrift_version>0.18.1</thrift_version>
<hessian_version>4.0.66</hessian_version>
<protobuf-java_version>3.23.4</protobuf-java_version>
<protobuf-java_version>3.24.1</protobuf-java_version>
<javax_annotation-api_version>1.3.2</javax_annotation-api_version>
<servlet_version>3.1.0</servlet_version>
<jetty_version>9.4.51.v20230217</jetty_version>
@ -129,18 +129,18 @@
<fst_version>2.57</fst_version>
<avro_version>1.11.1</avro_version>
<apollo_client_version>2.1.0</apollo_client_version>
<snakeyaml_version>2.0</snakeyaml_version>
<snakeyaml_version>2.1</snakeyaml_version>
<commons_lang3_version>3.12.0</commons_lang3_version>
<protostuff_version>1.8.0</protostuff_version>
<envoy_api_version>0.1.35</envoy_api_version>
<micrometer.version>1.11.2</micrometer.version>
<micrometer.version>1.11.3</micrometer.version>
<opentelemetry.version>1.26.0</opentelemetry.version>
<zipkin-reporter.version>2.16.4</zipkin-reporter.version>
<micrometer-tracing.version>1.1.3</micrometer-tracing.version>
<micrometer-tracing.version>1.1.4</micrometer-tracing.version>
<t_digest.version>3.3</t_digest.version>
<prometheus_client.version>0.16.0</prometheus_client.version>
<reactive.version>1.0.4</reactive.version>
<reactor.version>3.5.8</reactor.version>
<reactor.version>3.5.9</reactor.version>
<rxjava.version>2.2.21</rxjava.version>
<okhttp_version>3.14.9</okhttp_version>
@ -152,7 +152,7 @@
<nacos_version>2.2.4</nacos_version>
<sentinel.version>1.8.6</sentinel.version>
<seata.version>1.6.1</seata.version>
<grpc.version>1.56.1</grpc.version>
<grpc.version>1.57.2</grpc.version>
<grpc_contrib_verdion>0.8.1</grpc_contrib_verdion>
<jprotoc_version>1.2.2</jprotoc_version>
<!-- Log libs -->
@ -170,7 +170,7 @@
<eureka.version>1.10.18</eureka.version>
<!-- Fabric8 for Kubernetes -->
<fabric8_kubernetes_version>6.6.2</fabric8_kubernetes_version>
<fabric8_kubernetes_version>6.8.1</fabric8_kubernetes_version>
<!-- Alibaba -->
<alibaba_spring_context_support_version>1.0.11</alibaba_spring_context_support_version>

View File

@ -232,6 +232,13 @@
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-netty</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!-- tracing -->
<dependency>
@ -695,6 +702,7 @@
<include>org.apache.dubbo:dubbo-metrics-registry</include>
<include>org.apache.dubbo:dubbo-metrics-metadata</include>
<include>org.apache.dubbo:dubbo-metrics-config-center</include>
<include>org.apache.dubbo:dubbo-metrics-netty</include>
<include>org.apache.dubbo:dubbo-metrics-prometheus</include>
<include>org.apache.dubbo:dubbo-tracing</include>
<include>org.apache.dubbo:dubbo-monitor-api</include>

View File

@ -276,6 +276,11 @@
<artifactId>dubbo-metrics-config-center</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-netty</artifactId>
<version>${project.version}</version>
</dependency>
<!-- tracing -->
<dependency>

View File

@ -101,4 +101,14 @@ public class MetadataIdentifier extends BaseServiceMetadataIdentifier implements
return serviceInterface != null ? URL.buildKey(serviceInterface, getGroup(), getVersion()) : null;
}
@Override
public String toString() {
return "MetadataIdentifier{" +
"application='" + application + '\'' +
", serviceInterface='" + serviceInterface + '\'' +
", version='" + version + '\'' +
", group='" + group + '\'' +
", side='" + side + '\'' +
'}';
}
}

View File

@ -40,6 +40,7 @@ import static java.util.Collections.emptyList;
import static java.util.Collections.sort;
import static java.util.Collections.unmodifiableMap;
import static org.apache.dubbo.common.function.ThrowableFunction.execute;
import static org.apache.dubbo.common.utils.AnnotationUtils.isAnnotationPresent;
import static org.apache.dubbo.common.utils.AnnotationUtils.isAnyAnnotationPresent;
import static org.apache.dubbo.common.utils.ClassUtils.forName;
import static org.apache.dubbo.common.utils.ClassUtils.getAllInterfaces;
@ -197,8 +198,9 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest
for (Method serviceMethod : serviceMethods) {
if (overrides(serviceMethod, declaredServiceMethod)) {
serviceMethodsMap.put(serviceMethod, declaredServiceMethod);
// once method match ,break for decrease loop times
break;
// override method count > 1
// // once method match ,break for decrease loop times
// break;
}
}
}
@ -421,4 +423,16 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest
return supportedExtensionInstances;
}
public static boolean isServiceMethodAnnotationPresent(Class<?> serviceImpl, String annotationClass) {
List<Method> allMethods = getAllMethods(serviceImpl, excludedDeclaredClass(Object.class));
for (Method method : allMethods) {
if (isAnnotationPresent(method, annotationClass)) {
return true;
}
}
return false;
}
}

View File

@ -110,13 +110,17 @@ public class PathMatcher {
}
public static PathMatcher getInvokeCreatePathMatcher(String path, String version, String group, Integer port, String method) {
return new PathMatcher(path, version, group, port, method).noNeedHttpMethodCompare();
return new PathMatcher(path, version, group, port, method).compareHttpMethod(false);
}
public static PathMatcher getInvokeCreatePathMatcher(Method serviceMethod) {
return new PathMatcher(serviceMethod).setNeedCompareServiceMethod(true);
}
public static PathMatcher convertPathMatcher(PathMatcher pathMatcher) {
return getInvokeCreatePathMatcher(pathMatcher.path, pathMatcher.version, pathMatcher.group, pathMatcher.port, pathMatcher.httpMethod);
}
public boolean hasPathVariable() {
return hasPathVariable;
}
@ -134,8 +138,8 @@ public class PathMatcher {
return this;
}
private PathMatcher noNeedHttpMethodCompare() {
this.needCompareHttpMethod = false;
public PathMatcher compareHttpMethod(boolean needCompareHttpMethod) {
this.needCompareHttpMethod = needCompareHttpMethod;
return this;
}
@ -176,7 +180,7 @@ public class PathMatcher {
* @return
*/
private boolean httpMethodMatch(PathMatcher that) {
return !that.needCompareHttpMethod || !this.needCompareHttpMethod ? true: Objects.equals(this.httpMethod, that.httpMethod);
return !that.needCompareHttpMethod || !this.needCompareHttpMethod ? true : Objects.equals(this.httpMethod, that.httpMethod);
}
private boolean serviceMethodEqual(PathMatcher thatPathMatcher, PathMatcher thisPathMatcher) {

View File

@ -49,7 +49,9 @@ public class JAXRSServiceRestMetadataResolver extends AbstractServiceRestMetadat
@Override
protected boolean supports0(Class<?> serviceType) {
return isAnnotationPresent(serviceType, PATH_ANNOTATION_CLASS_NAME);
return isAnnotationPresent(serviceType, PATH_ANNOTATION_CLASS_NAME)
// method @Path
|| isServiceMethodAnnotationPresent(serviceType,PATH_ANNOTATION_CLASS_NAME);
}
@Override

View File

@ -41,6 +41,7 @@ import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.AN
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.CONTROLLER_ANNOTATION_CLASS;
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.FEIGN_CLIENT_CLASS;
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.REQUEST_MAPPING_ANNOTATION_CLASS;
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.REQUEST_MAPPING_ANNOTATION_CLASS_NAME;
/**
* {@link ServiceRestMetadataResolver}
@ -61,7 +62,8 @@ public class SpringMvcServiceRestMetadataResolver extends AbstractServiceRestMet
// class @Controller or @RequestMapping
return isAnnotationPresent(serviceType, CONTROLLER_ANNOTATION_CLASS)
|| isAnnotationPresent(serviceType, FEIGN_CLIENT_CLASS)
|| isAnnotationPresent(serviceType, REQUEST_MAPPING_ANNOTATION_CLASS);
|| isAnnotationPresent(serviceType, REQUEST_MAPPING_ANNOTATION_CLASS)// method @RequestMapping
|| isServiceMethodAnnotationPresent(serviceType, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
}
@Override

View File

@ -22,8 +22,8 @@ public interface MetricsConstants {
String INVOCATION = "metric_filter_invocation";
String METHOD_METRICS = "metric_filter_method_metrics";
String INVOCATION_METRICS_COUNTER = "metric_filter_invocation_counter";
String INVOCATION_SIDE = "metric_filter_side";
String INVOCATION_REQUEST_ERROR = "metric_request_error";
String ATTACHMENT_KEY_SERVICE = "serviceKey";
String ATTACHMENT_KEY_SIZE = "size";
@ -32,4 +32,6 @@ public interface MetricsConstants {
int SELF_INCREMENT_SIZE = 1;
String NETTY_METRICS_MAP = "nettyMetricsMap";
}

View File

@ -18,11 +18,12 @@
package org.apache.dubbo.metrics.aggregate;
import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
import com.tdunning.math.stats.Centroid;
import com.tdunning.math.stats.ScaleFunction;
import com.tdunning.math.stats.Sort;
import com.tdunning.math.stats.TDigest;
import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
import java.nio.ByteBuffer;
import java.util.AbstractCollection;
@ -285,16 +286,17 @@ public class DubboMergingDigest extends DubboAbstractTDigest {
throw new IllegalArgumentException("Cannot add NaN to t-digest");
}
int where;
synchronized (this) {
// There is a small probability of entering here
if (tempUsed.get() >= tempWeight.length - lastUsedCell.get() - 1) {
mergeNewValues();
}
where = tempUsed.getAndIncrement();
tempWeight[where] = w;
tempMean[where] = x;
unmergedWeight.addAndGet(w);
}
int where = tempUsed.getAndIncrement();
tempWeight[where] = w;
tempMean[where] = x;
unmergedWeight.addAndGet(w);
if (x < min) {
min = x;
}

View File

@ -34,7 +34,7 @@ import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE;
public abstract class CombMetricsCollector<E extends TimeCounterEvent> extends AbstractMetricsListener<E> implements ApplicationMetricsCollector<E>, ServiceMetricsCollector<E>, MethodMetricsCollector<E> {
private final BaseStatComposite stats;
protected final BaseStatComposite stats;
private MetricsEventMulticaster eventMulticaster;
@ -80,6 +80,10 @@ public abstract class CombMetricsCollector<E extends TimeCounterEvent> extends A
stats.calcMethodKeyRt(invocation, registryOpType, responseTime);
}
public void setAppNum(MetricsKey metricsKey,Long num) {
stats.setAppKey(metricsKey, num);
}
@Override
public void increment(MethodMetric methodMetric, MetricsKeyWrapper wrapper, int size) {
this.stats.incrementMethodKey(wrapper, methodMetric, size);
@ -108,5 +112,9 @@ public abstract class CombMetricsCollector<E extends TimeCounterEvent> extends A
public void onEventError(TimeCounterEvent event) {
eventMulticaster.publishErrorEvent(event);
}
protected BaseStatComposite getStats() {
return stats;
}
}

View File

@ -60,6 +60,12 @@ public class ApplicationStatComposite extends AbstractMetricsExport {
applicationNumStats.get(metricsKey).getAndAdd(size);
}
public void setAppKey(MetricsKey metricsKey, Long num){
if (!applicationNumStats.containsKey(metricsKey)) {
return;
}
applicationNumStats.get(metricsKey).set(num);
}
public List<MetricSample> export(MetricsCategory category) {
List<MetricSample> list = new ArrayList<>();

View File

@ -18,8 +18,10 @@
package org.apache.dubbo.metrics.data;
import org.apache.dubbo.metrics.collector.MetricsCollector;
import org.apache.dubbo.metrics.model.ApplicationMetric;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.metrics.model.MetricsCategory;
import org.apache.dubbo.metrics.model.ServiceKeyMetric;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.sample.MetricSample;
@ -29,6 +31,7 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
@ -70,11 +73,11 @@ public abstract class BaseStatComposite implements MetricsExport {
}
public void calcApplicationRt(String registryOpType, Long responseTime) {
rtStatComposite.calcApplicationRt(registryOpType, responseTime);
rtStatComposite.calcServiceKeyRt(registryOpType, responseTime, new ApplicationMetric(rtStatComposite.getApplicationModel()));
}
public void calcServiceKeyRt(String serviceKey, String registryOpType, Long responseTime) {
rtStatComposite.calcServiceKeyRt(serviceKey, registryOpType, responseTime);
rtStatComposite.calcServiceKeyRt(registryOpType, responseTime, new ServiceKeyMetric(rtStatComposite.getApplicationModel(), serviceKey));
}
public void calcServiceKeyRt(Invocation invocation, String registryOpType, Long responseTime) {
@ -89,6 +92,10 @@ public abstract class BaseStatComposite implements MetricsExport {
serviceStatComposite.setServiceKey(metricsKey, serviceKey, num);
}
public void setServiceKey(MetricsKeyWrapper metricsKey, String serviceKey, int num, Map<String, String> extra) {
serviceStatComposite.setExtraServiceKey(metricsKey, serviceKey, num, extra);
}
public void incrementApp(MetricsKey metricsKey, int size) {
applicationStatComposite.incrementSize(metricsKey, size);
}
@ -97,6 +104,10 @@ public abstract class BaseStatComposite implements MetricsExport {
serviceStatComposite.incrementServiceKey(metricsKeyWrapper, attServiceKey, size);
}
public void incrementServiceKey(MetricsKeyWrapper metricsKeyWrapper, String attServiceKey, Map<String, String> extra, int size) {
serviceStatComposite.incrementExtraServiceKey(metricsKeyWrapper, attServiceKey, extra, size);
}
public void incrementMethodKey(MetricsKeyWrapper metricsKeyWrapper, MethodMetric methodMetric, int size) {
methodStatComposite.incrementMethodKey(metricsKeyWrapper, methodMetric, size);
}
@ -118,4 +129,8 @@ public abstract class BaseStatComposite implements MetricsExport {
public RtStatComposite getRtStatComposite() {
return rtStatComposite;
}
public void setAppKey(MetricsKey metricsKey, Long num) {
applicationStatComposite.setAppKey(metricsKey, num);
}
}

View File

@ -17,7 +17,6 @@
package org.apache.dubbo.metrics.data;
import org.apache.dubbo.metrics.model.ApplicationMetric;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.metrics.model.Metric;
import org.apache.dubbo.metrics.model.MetricsCategory;
@ -89,20 +88,7 @@ public class RtStatComposite extends AbstractMetricsExport {
return singleRtStats;
}
public void calcApplicationRt(String registryOpType, Long responseTime) {
ApplicationMetric key = new ApplicationMetric(getApplicationModel());
for (LongContainer container : rtStats.get(registryOpType)) {
Number current = (Number) container.get(key);
if (current == null) {
container.putIfAbsent(key, container.getInitFunc().apply(key));
current = (Number) container.get(key);
}
container.getConsumerFunc().accept(responseTime, current);
}
}
public void calcServiceKeyRt(String serviceKey, String registryOpType, Long responseTime) {
ServiceKeyMetric key = new ServiceKeyMetric(getApplicationModel(), serviceKey);
public void calcServiceKeyRt(String registryOpType, Long responseTime, Metric key) {
for (LongContainer container : rtStats.get(registryOpType)) {
Number current = (Number) container.get(key);
if (current == null) {

View File

@ -53,21 +53,37 @@ public class ServiceStatComposite extends AbstractMetricsExport {
}
public void incrementServiceKey(MetricsKeyWrapper wrapper, String serviceKey, int size) {
incrementExtraServiceKey(wrapper, serviceKey, null, size);
}
public void incrementExtraServiceKey(MetricsKeyWrapper wrapper, String serviceKey, Map<String, String> extra, int size) {
if (!serviceWrapperNumStats.containsKey(wrapper)) {
return;
}
serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(getApplicationModel(), serviceKey), k -> new AtomicLong(0L)).getAndAdd(size);
ServiceKeyMetric serviceKeyMetric = new ServiceKeyMetric(getApplicationModel(), serviceKey);
if (extra != null) {
serviceKeyMetric.setExtraInfo(extra);
}
serviceWrapperNumStats.get(wrapper).computeIfAbsent(serviceKeyMetric, k -> new AtomicLong(0L)).getAndAdd(size);
// MetricsSupport.fillZero(serviceWrapperNumStats);
}
public void setServiceKey(MetricsKeyWrapper wrapper, String serviceKey, int num) {
setExtraServiceKey(wrapper, serviceKey, num, null);
}
public void setExtraServiceKey(MetricsKeyWrapper wrapper, String serviceKey, int num, Map<String, String> extra) {
if (!serviceWrapperNumStats.containsKey(wrapper)) {
return;
}
serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(getApplicationModel(), serviceKey), k -> new AtomicLong(0L)).set(num);
// MetricsSupport.fillZero(serviceWrapperNumStats);
ServiceKeyMetric serviceKeyMetric = new ServiceKeyMetric(getApplicationModel(), serviceKey);
if (extra != null) {
serviceKeyMetric.setExtraInfo(extra);
}
serviceWrapperNumStats.get(wrapper).computeIfAbsent(serviceKeyMetric, k -> new AtomicLong(0L)).set(num);
}
@Override
public List<MetricSample> export(MetricsCategory category) {
List<MetricSample> list = new ArrayList<>();
for (MetricsKeyWrapper wrapper : serviceWrapperNumStats.keySet()) {

View File

@ -23,6 +23,7 @@ import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.metrics.model.key.TypeWrapper;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
@ -40,7 +41,7 @@ public abstract class MetricsEvent {
private final String appName;
private final MetricsDispatcher metricsDispatcher;
private final Map<String, Object> attachment = new IdentityHashMap<>(8);
private final Map<String, Object> attachments = new IdentityHashMap<>(8);
public MetricsEvent(ApplicationModel source, TypeWrapper typeWrapper) {
this(source, null, null, typeWrapper);
@ -82,11 +83,19 @@ public abstract class MetricsEvent {
if (key == null) {
throw new MetricsNeverHappenException("Attachment key is null");
}
return (T) attachment.get(key);
return (T) attachments.get(key);
}
public Map<String, Object> getAttachments() {
return Collections.unmodifiableMap(attachments);
}
public void putAttachment(String key, Object value) {
attachment.put(key, value);
attachments.put(key, value);
}
public void putAttachments(Map<String, String> attachments) {
this.attachments.putAll(attachments);
}
public void setAvailable(boolean available) {

View File

@ -17,15 +17,22 @@
package org.apache.dubbo.metrics.event;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_METRICS_COLLECTOR_EXCEPTION;
/**
* Dispatches events to listeners, and provides ways for listeners to register themselves.
*/
public class MetricsEventBus {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(MetricsEventBus.class);
/**
* Posts an event to all registered subscribers and only once.
*
@ -36,7 +43,9 @@ public class MetricsEventBus {
return;
}
MetricsDispatcher dispatcher = event.getMetricsDispatcher();
Optional.ofNullable(dispatcher).ifPresent(d -> d.publishEvent(event));
Optional.ofNullable(dispatcher).ifPresent(d -> {
tryInvoke(() -> d.publishEvent(event));
});
}
/**
@ -63,27 +72,35 @@ public class MetricsEventBus {
*/
public static <T> T post(MetricsEvent event, Supplier<T> targetSupplier, Function<T, Boolean> trFunction) {
T result;
before(event);
tryInvoke(() -> before(event));
if (trFunction == null) {
try {
result = targetSupplier.get();
} catch (Throwable e) {
error(event);
tryInvoke(() -> error(event));
throw e;
}
after(event, result);
tryInvoke(() -> after(event, result));
} else {
// Custom failure status
result = targetSupplier.get();
if (trFunction.apply(result)) {
after(event, result);
tryInvoke(() -> after(event, result));
} else {
error(event);
tryInvoke(() -> error(event));
}
}
return result;
}
public static void tryInvoke(Runnable runnable) {
try {
runnable.run();
} catch (Throwable e) {
logger.warn(COMMON_METRICS_COLLECTOR_EXCEPTION, "", "", "invoke metric event error" + e.getMessage());
}
}
/**
* Applicable to the scene where execution and return are separated,
* eventSaveRunner saves the event, so that the calculation rt is introverted
@ -91,20 +108,22 @@ public class MetricsEventBus {
public static void before(MetricsEvent event) {
MetricsDispatcher dispatcher = validate(event);
if (dispatcher == null) return;
dispatcher.publishEvent(event);
tryInvoke(() -> dispatcher.publishEvent(event));
}
public static void after(MetricsEvent event, Object result) {
MetricsDispatcher dispatcher = validate(event);
if (dispatcher == null) return;
event.customAfterPost(result);
dispatcher.publishFinishEvent((TimeCounterEvent) event);
tryInvoke(() -> {
event.customAfterPost(result);
dispatcher.publishFinishEvent((TimeCounterEvent) event);
});
}
public static void error(MetricsEvent event) {
MetricsDispatcher dispatcher = validate(event);
if (dispatcher == null) return;
dispatcher.publishErrorEvent((TimeCounterEvent) event);
tryInvoke(() -> dispatcher.publishErrorEvent((TimeCounterEvent) event));
}
private static MetricsDispatcher validate(MetricsEvent event) {

View File

@ -27,6 +27,7 @@ import java.util.function.Consumer;
/**
* According to the event template of {@link MetricsEventBus},
* build a consistent static method for general and custom monitoring consume methods
*
*/
public abstract class AbstractMetricsKeyListener extends AbstractMetricsListener<TimeCounterEvent> implements MetricsLifeListener<TimeCounterEvent> {

View File

@ -28,7 +28,7 @@ public abstract class AbstractMetricsListener<E extends MetricsEvent> implements
private final Map<Integer, Boolean> eventMatchCache = new ConcurrentHashMap<>();
/**
* Whether to support the general determination of event points depends on the event type
* Only interested in events of the current listener's generic parameter type
*/
public boolean isSupport(MetricsEvent event) {
Boolean eventMatch = eventMatchCache.get(System.identityHashCode(event.getClass()));

View File

@ -21,19 +21,37 @@ import org.apache.dubbo.metrics.collector.CombMetricsCollector;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
/**
* App-level listener type, in most cases, can use the static method
* to produce an anonymous listener for general monitoring
*/
public class MetricsApplicationListener extends AbstractMetricsKeyListener {
public MetricsApplicationListener(MetricsKey metricsKey) {
super(metricsKey);
}
public static AbstractMetricsKeyListener onPostEventBuild(MetricsKey metricsKey, CombMetricsCollector collector) {
/**
* Perform auto-increment on the monitored key,
* Can use a custom listener instead of this generic operation
*
* @param metricsKey Monitor key
* @param collector Corresponding collector
*/
public static AbstractMetricsKeyListener onPostEventBuild(MetricsKey metricsKey, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onEvent(metricsKey,
event -> collector.increment(metricsKey)
event -> collector.increment(metricsKey)
);
}
public static AbstractMetricsKeyListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector collector) {
/**
* To end the monitoring normally, in addition to increasing the number of corresponding indicators,
* use the introspection method to calculate the relevant rt indicators
*
* @param metricsKey Monitor key
* @param collector Corresponding collector
*/
public static AbstractMetricsKeyListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onFinish(metricsKey,
event -> {
collector.increment(metricsKey);
@ -42,7 +60,10 @@ public class MetricsApplicationListener extends AbstractMetricsKeyListener {
);
}
public static AbstractMetricsKeyListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector collector) {
/**
* Similar to onFinishEventBuild
*/
public static AbstractMetricsKeyListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onError(metricsKey,
event -> {
collector.increment(metricsKey);

View File

@ -23,6 +23,11 @@ import org.apache.dubbo.metrics.model.MetricsSupport;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
/**
* Service-level listener type, in most cases, can use the static method
* to produce an anonymous listener for general monitoring.
* Similar to App-level
*/
public class MetricsServiceListener extends AbstractMetricsKeyListener {
public MetricsServiceListener(MetricsKey metricsKey) {

View File

@ -17,25 +17,14 @@
package org.apache.dubbo.metrics.model;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_VERSION_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
public class ApplicationMetric implements Metric {
private final ApplicationModel applicationModel;
private static final String version = Version.getVersion();
private static final String commitId = Version.getLastCommitId();
protected Map<String, String> extraInfo;
public ApplicationMetric(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
@ -49,27 +38,29 @@ public class ApplicationMetric implements Metric {
return getApplicationModel().getApplicationName();
}
public String getData() {
return version;
}
@Override
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, getApplicationName());
tags.put(TAG_APPLICATION_VERSION_KEY, version);
tags.put(MetricsKey.METADATA_GIT_COMMITID_METRIC.getName(), commitId);
return tags;
return MetricsSupport.applicationTags(applicationModel, getExtraInfo());
}
public Map<String, String> getExtraInfo() {
return extraInfo;
}
public void setExtraInfo(Map<String, String> extraInfo) {
this.extraInfo = extraInfo;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ApplicationMetric)) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ApplicationMetric that = (ApplicationMetric) o;
return Objects.equals(getApplicationName(), that.applicationModel.getApplicationName());
return getApplicationName().equals(that.applicationModel.getApplicationName()) && Objects.equals(extraInfo, that.extraInfo);
}
private volatile int hashCode;
@ -77,8 +68,9 @@ public class ApplicationMetric implements Metric {
@Override
public int hashCode() {
if (hashCode == 0) {
hashCode = Objects.hash(getApplicationName());
hashCode = Objects.hash(getApplicationName(), extraInfo);
}
return hashCode;
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.model;
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_ERROR_CODE;
/**
* ErrorCodeMetric. Provide tags for error code metrics.
*/
public class ErrorCodeMetric implements Metric {
private final String errorCode;
private final String applicationName;
public ErrorCodeMetric(String applicationName, String errorCode) {
this.errorCode = errorCode;
this.applicationName = applicationName;
}
@Override
public Map<String, String> getTags() {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_ERROR_CODE, errorCode);
tags.put(TAG_APPLICATION_NAME, applicationName);
return tags;
}
public String getErrorCode() {
return errorCode;
}
}

View File

@ -29,4 +29,6 @@ public enum MetricsCategory {
REGISTRY,
METADATA,
THREAD_POOL,
ERROR_CODE,
NETTY,
}

View File

@ -18,12 +18,12 @@
package org.apache.dubbo.metrics.model;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.lang.Nullable;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.metrics.collector.MethodMetricsCollector;
import org.apache.dubbo.metrics.collector.ServiceMetricsCollector;
import org.apache.dubbo.metrics.event.MetricsEvent;
import org.apache.dubbo.metrics.event.TimeCounterEvent;
import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
@ -62,6 +62,10 @@ public class MetricsSupport {
private static final String commitId = Version.getLastCommitId();
public static Map<String, String> applicationTags(ApplicationModel applicationModel) {
return applicationTags(applicationModel, null);
}
public static Map<String, String> applicationTags(ApplicationModel applicationModel, @Nullable Map<String, String> extraInfo) {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_IP, getLocalHost());
tags.put(TAG_HOSTNAME, getLocalHostName());
@ -69,23 +73,18 @@ public class MetricsSupport {
tags.put(TAG_APPLICATION_MODULE, applicationModel.getInternalId());
tags.put(TAG_APPLICATION_VERSION_KEY, version);
tags.put(MetricsKey.METADATA_GIT_COMMITID_METRIC.getName(), commitId);
if (CollectionUtils.isNotEmptyMap(extraInfo)) {
tags.putAll(extraInfo);
}
return tags;
}
public static Map<String, String> serviceTags(ApplicationModel applicationModel, String serviceKey) {
Map<String, String> tags = applicationTags(applicationModel);
public static Map<String, String> serviceTags(ApplicationModel applicationModel, String serviceKey, Map<String, String> extraInfo) {
Map<String, String> tags = applicationTags(applicationModel, extraInfo);
tags.put(TAG_INTERFACE_KEY, serviceKey);
return tags;
}
public static Map<String, String> methodTags(ApplicationModel applicationModel, String names) {
String[] keys = names.split("_");
if (keys.length != 2) {
throw new MetricsNeverHappenException("Error names: " + names);
}
return methodTags(applicationModel, keys[0], keys[1]);
}
public static Map<String, String> methodTags(ApplicationModel applicationModel, String serviceKey, String methodName) {
Map<String, String> tags = applicationTags(applicationModel);
tags.put(TAG_INTERFACE_KEY, serviceKey);
@ -211,7 +210,6 @@ public class MetricsSupport {
Invocation invocation = event.getAttachmentValue(INVOCATION);
if (invocation != null) {
collector.addServiceRt(invocation, placeType.getType(), event.getTimePair().calc());
return;
} else {
collector.addServiceRt((String) event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc());
}
@ -240,9 +238,9 @@ public class MetricsSupport {
}
/**
* Generate a complete indicator item for an interface/method
* Generate a complete indicator item for an interface/method
*/
public static <T> void fillZero(Map<MetricsKeyWrapper, Map<T, AtomicLong>> data) {
public static <T> void fillZero(Map<?, Map<T, AtomicLong>> data) {
if (CollectionUtils.isEmptyMap(data)) {
return;
}

View File

@ -35,7 +35,7 @@ public class ServiceKeyMetric extends ApplicationMetric {
@Override
public Map<String, String> getTags() {
return MetricsSupport.serviceTags(getApplicationModel(), serviceKey);
return MetricsSupport.serviceTags(getApplicationModel(), serviceKey, getExtraInfo());
}
public String getServiceKey() {
@ -47,16 +47,11 @@ public class ServiceKeyMetric extends ApplicationMetric {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
if (!(o instanceof ServiceKeyMetric)) {
return false;
}
ServiceKeyMetric that = (ServiceKeyMetric) o;
if (!getApplicationName().equals(that.getApplicationName())) {
return false;
}
return serviceKey.equals(that.serviceKey);
return serviceKey.equals(that.serviceKey) && Objects.equals(extraInfo, that.extraInfo);
}
@ -65,7 +60,7 @@ public class ServiceKeyMetric extends ApplicationMetric {
@Override
public int hashCode() {
if (hashCode == 0) {
hashCode = Objects.hash(getApplicationName(), serviceKey);
hashCode = Objects.hash(getApplicationName(), serviceKey, extraInfo);
}
return hashCode;
}

View File

@ -85,6 +85,7 @@ public class ThreadPoolMetric implements Metric{
return Objects.hash(applicationName, threadPoolName);
}
@Override
public Map<String, String> getTags() {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_IP, getLocalHost());

View File

@ -30,6 +30,7 @@ import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
public class ThreadPoolRejectMetric implements Metric{
private String applicationName;
private String threadPoolName;
@ -69,6 +70,7 @@ public class ThreadPoolRejectMetric implements Metric{
return Objects.hash(applicationName, threadPoolName);
}
@Override
public Map<String, String> getTags() {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_IP, getLocalHost());

View File

@ -43,7 +43,7 @@ public class MetricsCat {
}
/**
* @param tpFunc Ternary function, corresponding to finish and error events, because an additional record rt is required, and the type type of metricsKey is required
* @param tpFunc Ternary function, corresponding to finish and error events, because an additional record rt is required, and the type of metricsKey is required
*/
public MetricsCat(MetricsKey metricsKey, TpFunction<MetricsKey, MetricsPlaceValue, CombMetricsCollector, AbstractMetricsKeyListener> tpFunc) {
this.eventFunc = collector -> tpFunc.apply(metricsKey, placeType, collector);

View File

@ -17,131 +17,160 @@
package org.apache.dubbo.metrics.model.key;
/**
* Please follow a unified naming format as follows:
* dubbo_type_action_unit_otherfun
*/
public enum MetricsKey {
APPLICATION_METRIC_INFO("dubbo.application.info.total", "Total Application Info"),
APPLICATION_METRIC_INFO("application.info.total", "Total Application Info"),
CONFIGCENTER_METRIC_TOTAL("dubbo.configcenter.total", "Config Changed Total"),
CONFIGCENTER_METRIC_TOTAL("configcenter.total", "Config Changed Total"),
// provider metrics key
METRIC_REQUESTS("dubbo.%s.requests.total", "Total Requests"),
METRIC_REQUESTS_SUCCEED("dubbo.%s.requests.succeed.total", "Total Succeed Requests"),
METRIC_REQUEST_BUSINESS_FAILED("dubbo.%s.requests.business.failed.total", "Total Failed Business Requests"),
METRIC_REQUESTS("requests.total", "Total Requests"),
METRIC_REQUESTS_SUCCEED("requests.succeed.total", "Total Succeed Requests"),
METRIC_REQUEST_BUSINESS_FAILED("requests.business.failed.total", "Total Failed Business Requests"),
METRIC_REQUESTS_PROCESSING("dubbo.%s.requests.processing.total", "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"),
METRIC_REQUESTS_FAILED("dubbo.%s.requests.unknown.failed.total", "Total Unknown Failed Requests"),
METRIC_REQUESTS_TOTAL_FAILED("dubbo.%s.requests.failed.total", "Total Failed Requests"),
METRIC_REQUESTS_NETWORK_FAILED("dubbo.%s.requests.failed.network.total", "Total network Failed Requests"),
METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED("dubbo.%s.requests.failed.service.unavailable.total", "Total Service Unavailable Failed Requests"),
METRIC_REQUESTS_CODEC_FAILED("dubbo.%s.requests.failed.codec.total", "Total Codec Failed Requests"),
METRIC_REQUESTS_PROCESSING("requests.processing.total", "Processing Requests"),
METRIC_REQUESTS_TIMEOUT("requests.timeout.total", "Total Timeout Failed Requests"),
METRIC_REQUESTS_LIMIT("requests.limit.total", "Total Limit Failed Requests"),
METRIC_REQUESTS_FAILED("requests.unknown.failed.total", "Total Unknown Failed Requests"),
METRIC_REQUESTS_TOTAL_FAILED("requests.failed.total", "Total Failed Requests"),
METRIC_REQUESTS_NETWORK_FAILED("requests.failed.network.total", "Total network Failed Requests"),
METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED("requests.failed.service.unavailable.total", "Total Service Unavailable Failed Requests"),
METRIC_REQUESTS_CODEC_FAILED("requests.failed.codec.total", "Total Codec Failed Requests"),
METRIC_REQUESTS_TOTAL_AGG("dubbo.%s.requests.total.aggregate", "Aggregated Total Requests"),
METRIC_REQUESTS_SUCCEED_AGG("dubbo.%s.requests.succeed.aggregate", "Aggregated Succeed Requests"),
METRIC_REQUESTS_FAILED_AGG("dubbo.%s.requests.failed.aggregate", "Aggregated Failed Requests"),
METRIC_REQUEST_BUSINESS_FAILED_AGG("dubbo.%s.requests.business.failed.aggregate", "Aggregated Business Failed Requests"),
METRIC_REQUESTS_TIMEOUT_AGG("dubbo.%s.requests.timeout.failed.aggregate", "Aggregated timeout Failed Requests"),
METRIC_REQUESTS_LIMIT_AGG("dubbo.%s.requests.limit.aggregate", "Aggregated limit Requests"),
METRIC_REQUESTS_TOTAL_FAILED_AGG("dubbo.%s.requests.failed.total.aggregate", "Aggregated failed total Requests"),
METRIC_REQUESTS_NETWORK_FAILED_AGG("dubbo.%s.requests.failed.network.total.aggregate", "Aggregated failed network total Requests"),
METRIC_REQUESTS_CODEC_FAILED_AGG("dubbo.%s.requests.failed.codec.total.aggregate", "Aggregated failed codec total Requests"),
METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG("dubbo.%s.requests.failed.service.unavailable.total.aggregate", "Aggregated failed codec total Requests"),
METRIC_REQUESTS_TOTAL_AGG("requests.total.aggregate", "Aggregated Total Requests"),
METRIC_REQUESTS_SUCCEED_AGG("requests.succeed.aggregate", "Aggregated Succeed Requests"),
METRIC_REQUESTS_FAILED_AGG("requests.failed.aggregate", "Aggregated Failed Requests"),
METRIC_REQUEST_BUSINESS_FAILED_AGG("requests.business.failed.aggregate", "Aggregated Business Failed Requests"),
METRIC_REQUESTS_TIMEOUT_AGG("requests.timeout.failed.aggregate", "Aggregated timeout Failed Requests"),
METRIC_REQUESTS_LIMIT_AGG("requests.limit.aggregate", "Aggregated limit Requests"),
METRIC_REQUESTS_TOTAL_FAILED_AGG("requests.failed.total.aggregate", "Aggregated failed total Requests"),
METRIC_REQUESTS_NETWORK_FAILED_AGG("requests.failed.network.total.aggregate", "Aggregated failed network total Requests"),
METRIC_REQUESTS_CODEC_FAILED_AGG("requests.failed.codec.total.aggregate", "Aggregated failed codec total Requests"),
METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG("requests.failed.service.unavailable.total.aggregate", "Aggregated failed codec total Requests"),
METRIC_QPS("dubbo.%s.qps.total", "Query Per Seconds"),
METRIC_RT_LAST("dubbo.%s.rt.milliseconds.last", "Last Response Time"),
METRIC_RT_MIN("dubbo.%s.rt.milliseconds.min", "Min Response Time"),
METRIC_RT_MAX("dubbo.%s.rt.milliseconds.max", "Max Response Time"),
METRIC_RT_SUM("dubbo.%s.rt.milliseconds.sum", "Sum Response Time"),
METRIC_RT_AVG("dubbo.%s.rt.milliseconds.avg", "Average Response Time"),
METRIC_RT_P99("dubbo.%s.rt.milliseconds.p99", "Response Time P99"),
METRIC_RT_P95("dubbo.%s.rt.milliseconds.p95", "Response Time P95"),
METRIC_RT_P90("dubbo.%s.rt.milliseconds.p90", "Response Time P90"),
METRIC_RT_P50("dubbo.%s.rt.milliseconds.p50", "Response Time P50"),
METRIC_RT_MIN_AGG("dubbo.%s.rt.min.milliseconds.aggregate", "Aggregated Min Response"),
METRIC_RT_MAX_AGG("dubbo.%s.rt.max.milliseconds.aggregate", "Aggregated Max Response"),
METRIC_RT_AVG_AGG("dubbo.%s.rt.avg.milliseconds.aggregate", "Aggregated Avg Response"),
METRIC_QPS("qps.total", "Query Per Seconds"),
METRIC_RT_LAST("rt.milliseconds.last", "Last Response Time"),
METRIC_RT_MIN("rt.milliseconds.min", "Min Response Time"),
METRIC_RT_MAX("rt.milliseconds.max", "Max Response Time"),
METRIC_RT_SUM("rt.milliseconds.sum", "Sum Response Time"),
METRIC_RT_AVG("rt.milliseconds.avg", "Average Response Time"),
METRIC_RT_P99("rt.milliseconds.p99", "Response Time P99"),
METRIC_RT_P95("rt.milliseconds.p95", "Response Time P95"),
METRIC_RT_P90("rt.milliseconds.p90", "Response Time P90"),
METRIC_RT_P50("rt.milliseconds.p50", "Response Time P50"),
METRIC_RT_MIN_AGG("rt.milliseconds.min.aggregate", "Aggregated Min Response"),
METRIC_RT_MAX_AGG("rt.milliseconds.max.aggregate", "Aggregated Max Response"),
METRIC_RT_AVG_AGG("rt.milliseconds.avg.aggregate", "Aggregated Avg Response"),
// 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"),
METRIC_RT_HISTOGRAM("dubbo.%s.rt.milliseconds.histogram", "Response Time Histogram"),
REGISTER_METRIC_REQUESTS("registry.register.requests.total", "Total Register Requests"),
REGISTER_METRIC_REQUESTS_SUCCEED("registry.register.requests.succeed.total", "Succeed Register Requests"),
REGISTER_METRIC_REQUESTS_FAILED("registry.register.requests.failed.total", "Failed Register Requests"),
METRIC_RT_HISTOGRAM("rt.milliseconds.histogram", "Response Time Histogram"),
GENERIC_METRIC_REQUESTS("dubbo.%s.requests.total", "Total %s Requests"),
GENERIC_METRIC_REQUESTS_SUCCEED("dubbo.%s.requests.succeed.total", "Succeed %s Requests"),
GENERIC_METRIC_REQUESTS_FAILED("dubbo.%s.requests.failed.total", "Failed %s Requests"),
GENERIC_METRIC_REQUESTS("requests.total", "Total %s Requests"),
GENERIC_METRIC_REQUESTS_SUCCEED("requests.succeed.total", "Succeed %s Requests"),
GENERIC_METRIC_REQUESTS_FAILED("requests.failed.total", "Failed %s 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"),
SUBSCRIBE_METRIC_NUM("registry.subscribe.num.total", "Total Subscribe Num"),
SUBSCRIBE_METRIC_NUM_SUCCEED("registry.subscribe.num.succeed.total", "Succeed Subscribe Num"),
SUBSCRIBE_METRIC_NUM_FAILED("registry.subscribe.num.failed.total", "Failed Subscribe Num"),
// directory metrics key
DIRECTORY_METRIC_NUM_ALL("dubbo.registry.directory.num.all", "All Directory Urls"),
DIRECTORY_METRIC_NUM_VALID("dubbo.registry.directory.num.valid.total", "Valid Directory Urls"),
DIRECTORY_METRIC_NUM_TO_RECONNECT("dubbo.registry.directory.num.to_reconnect.total", "ToReconnect Directory Urls"),
DIRECTORY_METRIC_NUM_DISABLE("dubbo.registry.directory.num.disable.total", "Disable Directory Urls"),
DIRECTORY_METRIC_NUM_ALL("registry.directory.num.all", "All Directory Urls"),
DIRECTORY_METRIC_NUM_VALID("registry.directory.num.valid.total", "Valid Directory Urls"),
DIRECTORY_METRIC_NUM_TO_RECONNECT("registry.directory.num.to_reconnect.total", "ToReconnect Directory Urls"),
DIRECTORY_METRIC_NUM_DISABLE("registry.directory.num.disable.total", "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"),
NOTIFY_METRIC_REQUESTS("registry.notify.requests.total", "Total Notify Requests"),
NOTIFY_METRIC_NUM_LAST("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"),
THREAD_POOL_ACTIVE_SIZE("dubbo.thread.pool.active.size", "Thread Pool Active Size"),
THREAD_POOL_THREAD_COUNT("dubbo.thread.pool.thread.count", "Thread Pool Thread Count"),
THREAD_POOL_QUEUE_SIZE("dubbo.thread.pool.queue.size", "Thread Pool Queue Size"),
THREAD_POOL_THREAD_REJECT_COUNT("dubbo.thread.pool.reject.thread.count", "Thread Pool Reject Thread Count"),
THREAD_POOL_CORE_SIZE("thread.pool.core.size", "Thread Pool Core Size"),
THREAD_POOL_LARGEST_SIZE("thread.pool.largest.size", "Thread Pool Largest Size"),
THREAD_POOL_MAX_SIZE("thread.pool.max.size", "Thread Pool Max Size"),
THREAD_POOL_ACTIVE_SIZE("thread.pool.active.size", "Thread Pool Active Size"),
THREAD_POOL_THREAD_COUNT("thread.pool.thread.count", "Thread Pool Thread Count"),
THREAD_POOL_QUEUE_SIZE("thread.pool.queue.size", "Thread Pool Queue Size"),
THREAD_POOL_THREAD_REJECT_COUNT("thread.pool.reject.thread.count", "Thread Pool Reject Thread Count"),
// metadata push metrics key
METADATA_PUSH_METRIC_NUM("dubbo.metadata.push.num.total", "Total Push Num"),
METADATA_PUSH_METRIC_NUM_SUCCEED("dubbo.metadata.push.num.succeed.total", "Succeed Push Num"),
METADATA_PUSH_METRIC_NUM_FAILED("dubbo.metadata.push.num.failed.total", "Failed Push Num"),
METADATA_PUSH_METRIC_NUM("metadata.push.num.total", "Total Push Num"),
METADATA_PUSH_METRIC_NUM_SUCCEED("metadata.push.num.succeed.total", "Succeed Push Num"),
METADATA_PUSH_METRIC_NUM_FAILED("metadata.push.num.failed.total", "Failed Push Num"),
// metadata subscribe metrics key
METADATA_SUBSCRIBE_METRIC_NUM("dubbo.metadata.subscribe.num.total", "Total Metadata Subscribe Num"),
METADATA_SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.metadata.subscribe.num.succeed.total", "Succeed Metadata Subscribe Num"),
METADATA_SUBSCRIBE_METRIC_NUM_FAILED("dubbo.metadata.subscribe.num.failed.total", "Failed Metadata Subscribe Num"),
METADATA_SUBSCRIBE_METRIC_NUM("metadata.subscribe.num.total", "Total Metadata Subscribe Num"),
METADATA_SUBSCRIBE_METRIC_NUM_SUCCEED("metadata.subscribe.num.succeed.total", "Succeed Metadata Subscribe Num"),
METADATA_SUBSCRIBE_METRIC_NUM_FAILED("metadata.subscribe.num.failed.total", "Failed Metadata Subscribe Num"),
// register service metrics key
SERVICE_REGISTER_METRIC_REQUESTS("dubbo.registry.register.service.total", "Total Service-Level Register Requests"),
SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED("dubbo.registry.register.service.succeed.total", "Succeed Service-Level Register Requests"),
SERVICE_REGISTER_METRIC_REQUESTS_FAILED("dubbo.registry.register.service.failed.total", "Failed Service-Level Register Requests"),
SERVICE_REGISTER_METRIC_REQUESTS("registry.total", "Total Service-Level Register Requests"),
SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED("registry.succeed.total", "Succeed Service-Level Register Requests"),
SERVICE_REGISTER_METRIC_REQUESTS_FAILED("registry.failed.total", "Failed Service-Level Register Requests"),
// subscribe metrics key
SERVICE_SUBSCRIBE_METRIC_NUM("dubbo.registry.subscribe.service.num.total", "Total Service-Level Subscribe Num"),
SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.registry.subscribe.service.num.succeed.total", "Succeed Service-Level Num"),
SERVICE_SUBSCRIBE_METRIC_NUM_FAILED("dubbo.registry.subscribe.service.num.failed.total", "Failed Service-Level Num"),
SERVICE_SUBSCRIBE_METRIC_NUM("registry.subscribe.service.num.total", "Total Service-Level Subscribe Num"),
SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED("registry.subscribe.service.num.succeed.total", "Succeed Service-Level Num"),
SERVICE_SUBSCRIBE_METRIC_NUM_FAILED("registry.subscribe.service.num.failed.total", "Failed Service-Level Num"),
// store provider metadata service key
STORE_PROVIDER_METADATA("dubbo.metadata.store.provider.total", "Store Provider Metadata"),
STORE_PROVIDER_METADATA("metadata.store.provider.total", "Store Provider Metadata"),
STORE_PROVIDER_METADATA_SUCCEED("dubbo.metadata.store.provider.succeed.total", "Succeed Store Provider Metadata"),
STORE_PROVIDER_METADATA_SUCCEED("metadata.store.provider.succeed.total", "Succeed Store Provider Metadata"),
STORE_PROVIDER_METADATA_FAILED("dubbo.metadata.store.provider.failed.total", "Failed Store Provider Metadata"),
STORE_PROVIDER_METADATA_FAILED("metadata.store.provider.failed.total", "Failed Store Provider Metadata"),
METADATA_GIT_COMMITID_METRIC("git.commit.id", "Git Commit Id Metrics"),
// consumer metrics key
INVOKER_NO_AVAILABLE_COUNT("dubbo.consumer.invoker.no.available.count", "Request Throw No Invoker Available Exception Count"),
INVOKER_NO_AVAILABLE_COUNT("consumer.invoker.no.available.count", "Request Throw No Invoker Available Exception Count"),
// count the number of occurrences of each error code
ERROR_CODE_COUNT("dubbo.error.code.count","The Count Of Occurrences for Each Error Code"),
// netty metrics key
NETTY_ALLOCATOR_HEAP_MEMORY_USED("netty.allocator.memory.used", "Netty Allocator Memory Used"),
NETTY_ALLOCATOR_DIRECT_MEMORY_USED("netty.allocator.direct.memory.used", "Netty Allocator Direct Memory Used"),
NETTY_ALLOCATOR_PINNED_DIRECT_MEMORY("netty.allocator.pinned.direct.memory", "Netty Allocator Pinned Direct Memory"),
NETTY_ALLOCATOR_PINNED_HEAP_MEMORY("netty.allocator.pinned.heap.memory", "Netty Allocator Pinned Heap Memory"),
NETTY_ALLOCATOR_HEAP_ARENAS_NUM("netty.allocator.heap.arenas.num", "Netty Allocator Heap Arenas Num"),
NETTY_ALLOCATOR_DIRECT_ARENAS_NUM("netty.allocator.direct.arenas.num", "Netty Allocator Direct Arenas Num"),
NETTY_ALLOCATOR_NORMAL_CACHE_SIZE("netty.allocator.normal.cache.size", "Netty Allocator Normal Cache Size"),
NETTY_ALLOCATOR_SMALL_CACHE_SIZE("netty.allocator.small.cache.size", "Netty Allocator Small Cache Size"),
NETTY_ALLOCATOR_THREAD_LOCAL_CACHES_NUM("netty.allocator.thread.local.caches.num", "Netty Allocator Thread Local Caches Num"),
NETTY_ALLOCATOR_CHUNK_SIZE("netty.allocator.chunk.size", "Netty Allocator Chunk Size"),
;
private String name;
private String nameSuffix;
private String description;
public final String getName() {
return this.name;
return "dubbo." + nameSuffix;
}
public final String getNameByType(String type) {
return String.format(name, type);
return "dubbo." + type + "." + nameSuffix;
}
public static MetricsKey getMetricsByName(String name){
for (MetricsKey metricsKey : MetricsKey.values()) {
if (metricsKey.getName().equals(name)) {
return metricsKey;
}
}
return null;
}
public final String getDescription() {
return this.description;
}
MetricsKey(String name, String description) {
this.name = name;
MetricsKey(String nameSuffix, String description) {
this.nameSuffix = nameSuffix;
this.description = description;
}
}

View File

@ -18,11 +18,8 @@
package org.apache.dubbo.metrics.model.key;
import io.micrometer.common.lang.Nullable;
import org.apache.dubbo.metrics.model.MetricsSupport;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.Map;
import java.util.Objects;
/**
@ -88,7 +85,7 @@ public class MetricsKeyWrapper {
return metricsKey.getName();
}
try {
return String.format(metricsKey.getName(), getType());
return metricsKey.getNameByType(getType());
} catch (Exception ignore) {
return metricsKey.getName();
}
@ -105,19 +102,6 @@ public class MetricsKeyWrapper {
}
}
public Map<String, String> tagName(ApplicationModel applicationModel, String key) {
MetricsLevel level = getLevel();
switch (level) {
case APP:
return MetricsSupport.applicationTags(applicationModel);
case SERVICE:
return MetricsSupport.serviceTags(applicationModel, key);
case METHOD:
return MetricsSupport.methodTags(applicationModel, key);
}
return MetricsSupport.applicationTags(applicationModel);
}
public static MetricsKeyWrapper wrapper(MetricsKey metricsKey) {
return new MetricsKeyWrapper(metricsKey, null);
}

View File

@ -18,5 +18,5 @@
package org.apache.dubbo.metrics.model.key;
public enum MetricsLevel {
APP, SERVICE, METHOD, CONFIG
APP, SERVICE, METHOD, CONFIG, REGISTRY
}

View File

@ -18,6 +18,7 @@
package org.apache.dubbo.metrics.aggregate;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import java.util.concurrent.ExecutorService;
@ -37,6 +38,7 @@ class TimeWindowQuantileTest {
}
@Test
@RepeatedTest(100)
void testMulti() {
ExecutorService executorService = Executors.newFixedThreadPool(200);
@ -51,12 +53,14 @@ class TimeWindowQuantileTest {
quantile.add(finalI));
}
index++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// try {
// Thread.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
executorService.shutdown();
}
}

View File

@ -20,16 +20,16 @@ package org.apache.dubbo.metrics.collector;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.metrics.DefaultConstants;
import org.apache.dubbo.metrics.collector.sample.MetricsCountSampleConfigurer;
import org.apache.dubbo.metrics.collector.sample.ErrorCodeSampler;
import org.apache.dubbo.metrics.collector.sample.MetricsSampler;
import org.apache.dubbo.metrics.collector.sample.SimpleMetricsCountSampler;
import org.apache.dubbo.metrics.collector.sample.ThreadPoolMetricsSampler;
import org.apache.dubbo.metrics.collector.sample.MetricsCountSampleConfigurer;
import org.apache.dubbo.metrics.data.BaseStatComposite;
import org.apache.dubbo.metrics.data.MethodStatComposite;
import org.apache.dubbo.metrics.data.RtStatComposite;
import org.apache.dubbo.metrics.event.DefaultSubDispatcher;
import org.apache.dubbo.metrics.event.MetricsEvent;
import org.apache.dubbo.metrics.event.RequestBeforeEvent;
import org.apache.dubbo.metrics.event.RequestEvent;
import org.apache.dubbo.metrics.model.ApplicationMetric;
import org.apache.dubbo.metrics.model.MetricsCategory;
@ -54,9 +54,15 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
private boolean collectEnabled = false;
private volatile boolean threadpoolCollectEnabled = false;
private final ThreadPoolMetricsSampler threadPoolSampler = new ThreadPoolMetricsSampler(this);
private final ErrorCodeSampler errorCodeSampler;
private String applicationName;
private final ApplicationModel applicationModel;
private final List<MetricsSampler> samplers = new ArrayList<>();
public DefaultMetricsCollector(ApplicationModel applicationModel) {
@ -75,8 +81,9 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
}
});
super.setEventMulticaster(new DefaultSubDispatcher(this));
samplers.add(applicationSampler);
samplers.add(threadPoolSampler);
this.samplers.add(applicationSampler);
this.samplers.add(threadPoolSampler);
this.errorCodeSampler = new ErrorCodeSampler(this);
this.applicationModel = applicationModel;
}
@ -100,6 +107,7 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
this.collectEnabled = collectEnabled;
}
@Override
public boolean isCollectEnabled() {
return collectEnabled;
}
@ -138,7 +146,7 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
@Override
public boolean isSupport(MetricsEvent event) {
return event instanceof RequestEvent || event instanceof RequestBeforeEvent;
return event instanceof RequestEvent;
}
public SimpleMetricsCountSampler<String, MetricsEvent.Type, ApplicationMetric> applicationSampler = new SimpleMetricsCountSampler<String, MetricsEvent.Type, ApplicationMetric>() {

View File

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metrics.collector.sample;
import org.apache.dubbo.common.logger.LogListener;
import org.apache.dubbo.common.logger.support.FailsafeErrorTypeAwareLogger;
import org.apache.dubbo.metrics.model.key.MetricsKey;
/**
* Listen the log of all {@link FailsafeErrorTypeAwareLogger} instances, and add error code count to {@link ErrorCodeSampler}.
*/
public class ErrorCodeMetricsListenRegister implements LogListener {
private final ErrorCodeSampler errorCodeSampler;
public ErrorCodeMetricsListenRegister(ErrorCodeSampler errorCodeSampler){
FailsafeErrorTypeAwareLogger.registerGlobalListen(this);
this.errorCodeSampler = errorCodeSampler;
this.errorCodeSampler.addMetricName(MetricsKey.ERROR_CODE_COUNT.getName());
}
@Override
public void onMessage(String code, String msg) {
errorCodeSampler.inc(code, MetricsKey.ERROR_CODE_COUNT.getName());
}
}

View File

@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metrics.collector.sample;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.model.ErrorCodeMetric;
import org.apache.dubbo.metrics.model.MetricsCategory;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
/**
* This sampler is used to count the number of occurrences of each error code.
*/
public class ErrorCodeSampler extends MetricsNameCountSampler<String, String, ErrorCodeMetric> {
private final ErrorCodeMetricsListenRegister register;
/**
* Map<ErrorCode,Metric>
*/
private final Map<String, ErrorCodeMetric> errorCodeMetrics;
public ErrorCodeSampler(DefaultMetricsCollector collector) {
super(collector, MetricsCategory.ERROR_CODE, MetricsKey.ERROR_CODE_COUNT);
this.register = new ErrorCodeMetricsListenRegister(this);
this.errorCodeMetrics = new ConcurrentHashMap<>();
}
@Override
protected MetricSample provideMetricsSample(ErrorCodeMetric metric, AtomicLong count, MetricsKey metricsKey, MetricsCategory metricsCategory) {
return new CounterMetricSample<>(
metricsKey.getNameByType(metric.getErrorCode()),
metricsKey.getDescription(),
metric.getTags(),
metricsCategory,
count
);
}
@Override
protected void countConfigure(MetricsCountSampleConfigurer<String, String, ErrorCodeMetric> sampleConfigure) {
sampleConfigure.configureMetrics(configure -> {
String errorCode = configure.getSource();
ErrorCodeMetric metric = errorCodeMetrics.get(errorCode);
if (metric == null) {
metric = new ErrorCodeMetric(collector.getApplicationModel().getApplicationName(), errorCode);
errorCodeMetrics.put(errorCode, metric);
}
return metric;
});
}
}

View File

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metrics.collector.sample;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.model.Metric;
import org.apache.dubbo.metrics.model.MetricsCategory;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
public abstract class MetricsNameCountSampler<S, K, M extends Metric> extends SimpleMetricsCountSampler<S, K, M> {
protected final DefaultMetricsCollector collector;
protected final Set<K> metricNames = new ConcurrentHashSet<>();
protected final MetricsCategory metricsCategory;
protected final MetricsKey metricsKey;
public MetricsNameCountSampler(DefaultMetricsCollector collector,MetricsCategory metricsCategory,MetricsKey metricsKey) {
this.metricsCategory = metricsCategory;
this.metricsKey = metricsKey;
this.collector = collector;
this.collector.addSampler(this);
}
public void addMetricName(K name) {
this.metricNames.add(name);
}
@Override
public List<MetricSample> sample() {
List<MetricSample> metricSamples = new ArrayList<>();
metricNames.forEach(name -> collect(metricSamples, name));
return metricSamples;
}
private void collect(List<MetricSample> samples, K metricName) {
getCount(metricName)
.filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) ->
samples.add(provideMetricsSample(k,v,metricsKey,metricsCategory))));
}
protected abstract MetricSample provideMetricsSample(M metric,AtomicLong count,MetricsKey metricsKey,MetricsCategory metricsCategory);
}

View File

@ -36,6 +36,7 @@ public abstract class SimpleMetricsCountSampler<S, K, M extends Metric>
implements MetricsCountSampler<S, K, M> {
private final ConcurrentMap<M, AtomicLong> EMPTY_COUNT = new ConcurrentHashMap<>();
private final Map<K, ConcurrentMap<M, AtomicLong>> metricCounter = new ConcurrentHashMap<>();
@Override

View File

@ -16,65 +16,33 @@
*/
package org.apache.dubbo.metrics.collector.sample;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.model.Metric;
import org.apache.dubbo.metrics.model.MetricsCategory;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.ThreadPoolRejectMetric;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.ToDoubleFunction;
import static org.apache.dubbo.metrics.model.MetricsCategory.THREAD_POOL;
public class ThreadRejectMetricsCountSampler extends SimpleMetricsCountSampler<String, String, ThreadPoolRejectMetric> {
public class ThreadRejectMetricsCountSampler extends MetricsNameCountSampler<String, String, ThreadPoolRejectMetric> {
private final DefaultMetricsCollector collector;
private final Set<String> metricNames = new ConcurrentHashSet<>();
public ThreadRejectMetricsCountSampler(DefaultMetricsCollector collector) {
this.collector = collector;
this.collector.addSampler(this);
}
public void addMetricName(String name){
this.metricNames.add(name);
super(collector, THREAD_POOL,MetricsKey.THREAD_POOL_THREAD_REJECT_COUNT);
}
@Override
public List<MetricSample> sample() {
List<MetricSample> metricSamples = new ArrayList<>();
metricNames.stream().forEach(name->collect(metricSamples,name));
return metricSamples;
}
private void collect(List<MetricSample> list, String metricName) {
count(list, metricName, MetricsKey.THREAD_POOL_THREAD_REJECT_COUNT);
}
private <T extends Metric> void count(List<MetricSample> list, String metricName, MetricsKey metricsKey) {
getCount(metricName).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) ->
list.add(getGaugeMetricSample(metricsKey, k, THREAD_POOL, v, AtomicLong::get))));
}
private <T> GaugeMetricSample<T> getGaugeMetricSample(MetricsKey metricsKey,
ThreadPoolRejectMetric methodMetric,
MetricsCategory metricsCategory,
T value,
ToDoubleFunction<T> apply) {
protected MetricSample provideMetricsSample(ThreadPoolRejectMetric metric, AtomicLong count, MetricsKey metricsKey, MetricsCategory metricsCategory) {
return new GaugeMetricSample<>(
metricsKey.getNameByType(methodMetric.getThreadPoolName()),
metricsKey.getNameByType(metric.getThreadPoolName()),
metricsKey.getDescription(),
methodMetric.getTags(),
metric.getTags(),
metricsCategory,
value,
apply);
count,
AtomicLong::get);
}
@Override

View File

@ -43,17 +43,16 @@ public final class DefaultSubDispatcher extends SimpleMetricsEventMulticaster {
super.addListener(categoryOverall.getFinish().getEventFunc().apply(collector));
super.addListener(categoryOverall.getError().getEventFunc().apply(collector));
super.addListener(new MetricsListener<RequestBeforeEvent>() {
super.addListener(new MetricsListener<RequestEvent>() {
@Override
public boolean isSupport(MetricsEvent event) {
return event instanceof RequestBeforeEvent;
return event instanceof RequestEvent && ((RequestEvent) event).isRequestErrorEvent();
}
private final MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD);
@Override
public void onEvent(RequestBeforeEvent event) {
public void onEvent(RequestEvent event) {
MetricsSupport.increment(METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED, dynamicPlaceType, (MethodMetricsCollector) collector, event);
}
});
@ -97,6 +96,7 @@ public final class DefaultSubDispatcher extends SimpleMetricsEventMulticaster {
MetricsSupport.incrAndAddRt(targetKey, dynamicPlaceType, (MethodMetricsCollector) collector, event);
}
)));
}
}

View File

@ -1,51 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metrics.event;
import org.apache.dubbo.metrics.MetricsConstants;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.metrics.model.MetricsSupport;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsLevel;
import org.apache.dubbo.metrics.model.key.TypeWrapper;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
/**
* Acts on MetricsClusterFilter to monitor exceptions that occur before request execution
*/
public class RequestBeforeEvent extends TimeCounterEvent {
public RequestBeforeEvent(ApplicationModel source, String appName, MetricsDispatcher metricsDispatcher, TypeWrapper typeWrapper) {
super(source, appName, metricsDispatcher, typeWrapper);
}
private static final TypeWrapper REQUEST_BEFORE_EVENT = new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS);
public static RequestBeforeEvent toEvent(ApplicationModel applicationModel, String appName, MetricsDispatcher metricsDispatcher, Invocation invocation, String side) {
RequestBeforeEvent event = new RequestBeforeEvent(applicationModel, appName, metricsDispatcher, REQUEST_BEFORE_EVENT);
event.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
event.putAttachment(MetricsConstants.INVOCATION_SIDE, side);
event.putAttachment(MetricsConstants.INVOCATION, invocation);
event.putAttachment(MetricsConstants.METHOD_METRICS, new MethodMetric(applicationModel, invocation));
return event;
}
}

View File

@ -23,6 +23,7 @@ import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.metrics.model.MetricsSupport;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsLevel;
import org.apache.dubbo.metrics.model.key.TypeWrapper;
import org.apache.dubbo.rpc.Invocation;
@ -39,7 +40,8 @@ import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUEST_BUSIN
* Request related events
*/
public class RequestEvent extends TimeCounterEvent {
private static final TypeWrapper TYPE_WRAPPER = new TypeWrapper(MetricsLevel.SERVICE, METRIC_REQUESTS, METRIC_REQUESTS_SUCCEED, METRIC_REQUEST_BUSINESS_FAILED);
private static final TypeWrapper REQUEST_EVENT = new TypeWrapper(MetricsLevel.SERVICE, METRIC_REQUESTS, METRIC_REQUESTS_SUCCEED, METRIC_REQUEST_BUSINESS_FAILED);
private static final TypeWrapper REQUEST_ERROR_EVENT = new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS);
public RequestEvent(ApplicationModel applicationModel, String appName, MetricsDispatcher metricsDispatcher, DefaultMetricsCollector collector, TypeWrapper TYPE_WRAPPER) {
super(applicationModel, appName, metricsDispatcher, TYPE_WRAPPER);
@ -56,7 +58,7 @@ public class RequestEvent extends TimeCounterEvent {
MetricsDispatcher metricsDispatcher, DefaultMetricsCollector collector,
Invocation invocation, String side) {
MethodMetric methodMetric = new MethodMetric(applicationModel, invocation);
RequestEvent requestEvent = new RequestEvent(applicationModel, appName, metricsDispatcher, collector, TYPE_WRAPPER);
RequestEvent requestEvent = new RequestEvent(applicationModel, appName, metricsDispatcher, collector, REQUEST_EVENT);
requestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
requestEvent.putAttachment(MetricsConstants.METHOD_METRICS, methodMetric);
requestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
@ -74,4 +76,21 @@ public class RequestEvent extends TimeCounterEvent {
}
super.putAttachment(METRIC_THROWABLE, ((Result) postResult).getException());
}
/**
* Acts on MetricsClusterFilter to monitor exceptions that occur before request execution
*/
public static RequestEvent toRequestErrorEvent(ApplicationModel applicationModel, String appName, MetricsDispatcher metricsDispatcher, Invocation invocation, String side, int code) {
RequestEvent event = new RequestEvent(applicationModel, appName, metricsDispatcher, null, REQUEST_ERROR_EVENT);
event.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
event.putAttachment(MetricsConstants.INVOCATION_SIDE, side);
event.putAttachment(MetricsConstants.INVOCATION, invocation);
event.putAttachment(MetricsConstants.INVOCATION_REQUEST_ERROR, code);
event.putAttachment(MetricsConstants.METHOD_METRICS, new MethodMetric(applicationModel, invocation));
return event;
}
public boolean isRequestErrorEvent(){
return super.getAttachmentValue(MetricsConstants.INVOCATION_REQUEST_ERROR) != null;
}
}

View File

@ -21,7 +21,6 @@ import io.micrometer.core.instrument.FunctionCounter;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.common.constants.MetricsConstants;
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
@ -38,7 +37,6 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics;
import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics;
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
@ -49,7 +47,6 @@ import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@ -112,21 +109,19 @@ public abstract class AbstractMetricsReporter implements MetricsReporter {
private void addJvmMetrics() {
boolean enableJvmMetrics = url.getParameter(ENABLE_JVM_METRICS_KEY, false);
if (enableJvmMetrics) {
Tags extraTags = Tags.of(MetricsConstants.TAG_APPLICATION_NAME,
Optional.ofNullable(applicationModel.getApplicationName()).orElse(""));
new ClassLoaderMetrics(extraTags).bindTo(compositeRegistry);
new JvmMemoryMetrics(extraTags).bindTo(compositeRegistry);
new ClassLoaderMetrics().bindTo(compositeRegistry);
new JvmMemoryMetrics().bindTo(compositeRegistry);
@SuppressWarnings("java:S2095")
// Do not change JvmGcMetrics to try-with-resources as the JvmGcMetrics will not be available after (auto-)closing.
// See https://github.com/micrometer-metrics/micrometer/issues/1492
JvmGcMetrics jvmGcMetrics = new JvmGcMetrics(extraTags);
JvmGcMetrics jvmGcMetrics = new JvmGcMetrics();
jvmGcMetrics.bindTo(compositeRegistry);
Runtime.getRuntime().addShutdownHook(new Thread(jvmGcMetrics::close));
bindTo(new ProcessorMetrics(extraTags));
new JvmThreadMetrics(extraTags).bindTo(compositeRegistry);
bindTo(new UptimeMetrics(extraTags));
bindTo(new ProcessorMetrics());
new JvmThreadMetrics().bindTo(compositeRegistry);
bindTo(new UptimeMetrics());
}
}

View File

@ -22,7 +22,7 @@ import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.event.MetricsDispatcher;
import org.apache.dubbo.metrics.event.MetricsEventBus;
import org.apache.dubbo.metrics.event.RequestBeforeEvent;
import org.apache.dubbo.metrics.event.RequestEvent;
import org.apache.dubbo.rpc.BaseFilter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
@ -73,7 +73,7 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener,
if (t instanceof RpcException) {
RpcException e = (RpcException) t;
if (e.isForbidden()) {
MetricsEventBus.publish(RequestBeforeEvent.toEvent(applicationModel, appName, metricsDispatcher, invocation, CONSUMER_SIDE));
MetricsEventBus.publish(RequestEvent.toRequestErrorEvent(applicationModel, appName, metricsDispatcher, invocation, CONSUMER_SIDE, e.getCode()));
}
}
}

View File

@ -31,7 +31,6 @@ import org.apache.dubbo.metrics.TestMetricsInvoker;
import org.apache.dubbo.metrics.aggregate.TimeWindowCounter;
import org.apache.dubbo.metrics.event.MetricsDispatcher;
import org.apache.dubbo.metrics.event.MetricsEventBus;
import org.apache.dubbo.metrics.event.RequestBeforeEvent;
import org.apache.dubbo.metrics.event.RequestEvent;
import org.apache.dubbo.metrics.filter.MetricsFilter;
import org.apache.dubbo.metrics.listener.MetricsListener;
@ -143,9 +142,10 @@ class AggregateMetricsCollectorTest {
void testListener() {
AggregateMetricsCollector metricsCollector = new AggregateMetricsCollector(applicationModel);
RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, null, null, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION);
Assertions.assertTrue(metricsCollector.isSupport(event));
Assertions.assertFalse(metricsCollector.isSupport(beforeEvent));
Assertions.assertTrue(metricsCollector.isSupport(beforeEvent));
}
@AfterEach

View File

@ -22,7 +22,6 @@ import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metrics.TestMetricsInvoker;
import org.apache.dubbo.metrics.event.MetricsDispatcher;
import org.apache.dubbo.metrics.event.RequestBeforeEvent;
import org.apache.dubbo.metrics.event.RequestEvent;
import org.apache.dubbo.metrics.filter.MetricsFilter;
import org.apache.dubbo.metrics.model.MetricsSupport;
@ -114,7 +113,8 @@ class DefaultCollectorTest {
void testListener() {
DefaultMetricsCollector metricsCollector = new DefaultMetricsCollector(applicationModel);
RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, null, null, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION);
Assertions.assertTrue(metricsCollector.isSupport(event));
Assertions.assertTrue(metricsCollector.isSupport(beforeEvent));
}

View File

@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metrics.metrics.model.sample;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.common.utils.ReflectionUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.collector.sample.ErrorCodeMetricsListenRegister;
import org.apache.dubbo.metrics.collector.sample.ErrorCodeSampler;
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
public class ErrorCodeSampleTest {
@Test
void testErrorCodeMetric() {
FrameworkModel frameworkModel = FrameworkModel.defaultModel();
ApplicationModel applicationModel = frameworkModel.newApplication();
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("MyApplication1");
applicationModel.getApplicationConfigManager().setApplication(applicationConfig);
DefaultMetricsCollector defaultMetricsCollector = new DefaultMetricsCollector(applicationModel);
defaultMetricsCollector.setCollectEnabled(true);
ErrorCodeSampler sampler = (ErrorCodeSampler) ReflectionUtils.getField(defaultMetricsCollector, "errorCodeSampler");
ErrorCodeMetricsListenRegister register = (ErrorCodeMetricsListenRegister) ReflectionUtils.getField(sampler, "register");
register.onMessage("0-1", null);
register.onMessage("0-1", null);
register.onMessage("0-2", null);
register.onMessage("0-2", null);
register.onMessage("1-2", null);
register.onMessage("1-2", null);
register.onMessage("1-3", null);
register.onMessage("1-3", null);
List<MetricSample> samples = defaultMetricsCollector.collect();
Assert.assertTrue(samples.size() == 4,"Wrong number of samples.");
samples.forEach(metricSample -> Assert.assertTrue(((AtomicLong)((CounterMetricSample<?>)metricSample).getValue()).get() == 2L,"Sample count error."));
System.out.println(samples);
}
}

View File

@ -0,0 +1,40 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>dubbo-metrics-netty</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>The metrics module of dubbo project</description>
<properties>
<skip_maven_deploy>false</skip_maven_deploy>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-api</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,44 @@
/*
* 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;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import java.util.Arrays;
import java.util.List;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_CHUNK_SIZE;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_DIRECT_ARENAS_NUM;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_DIRECT_MEMORY_USED;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_HEAP_ARENAS_NUM;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_HEAP_MEMORY_USED;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_NORMAL_CACHE_SIZE;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_PINNED_DIRECT_MEMORY;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_PINNED_HEAP_MEMORY;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_SMALL_CACHE_SIZE;
import static org.apache.dubbo.metrics.model.key.MetricsKey.NETTY_ALLOCATOR_THREAD_LOCAL_CACHES_NUM;
public interface NettyMetricsConstants {
// App-level
List<MetricsKey> APP_LEVEL_KEYS = Arrays.asList(NETTY_ALLOCATOR_HEAP_MEMORY_USED,NETTY_ALLOCATOR_DIRECT_MEMORY_USED
,NETTY_ALLOCATOR_PINNED_DIRECT_MEMORY,NETTY_ALLOCATOR_PINNED_HEAP_MEMORY,NETTY_ALLOCATOR_HEAP_ARENAS_NUM
,NETTY_ALLOCATOR_DIRECT_ARENAS_NUM,NETTY_ALLOCATOR_NORMAL_CACHE_SIZE,NETTY_ALLOCATOR_SMALL_CACHE_SIZE,NETTY_ALLOCATOR_THREAD_LOCAL_CACHES_NUM
,NETTY_ALLOCATOR_CHUNK_SIZE);
}

View File

@ -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.collector;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.metrics.collector.CombMetricsCollector;
import org.apache.dubbo.metrics.collector.MetricsCollector;
import org.apache.dubbo.metrics.data.ApplicationStatComposite;
import org.apache.dubbo.metrics.data.BaseStatComposite;
import org.apache.dubbo.metrics.data.RtStatComposite;
import org.apache.dubbo.metrics.data.ServiceStatComposite;
import org.apache.dubbo.metrics.model.MetricsCategory;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.registry.NettyMetricsConstants;
import org.apache.dubbo.metrics.registry.event.NettyEvent;
import org.apache.dubbo.metrics.registry.event.NettySubDispatcher;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* Netty implementation of {@link MetricsCollector}
*/
@Activate
public class NettyMetricsCollector extends CombMetricsCollector<NettyEvent> {
private Boolean collectEnabled = null;
private final ApplicationModel applicationModel;
public NettyMetricsCollector(ApplicationModel applicationModel) {
super(new BaseStatComposite(applicationModel) {
@Override
protected void init(ApplicationStatComposite applicationStatComposite) {
super.init(applicationStatComposite);
applicationStatComposite.init(NettyMetricsConstants.APP_LEVEL_KEYS);
}
@Override
protected void init(ServiceStatComposite serviceStatComposite) {
super.init(serviceStatComposite);
}
@Override
protected void init(RtStatComposite rtStatComposite) {
super.init(rtStatComposite);
}
});
super.setEventMulticaster(new NettySubDispatcher(this));
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.getEnableNetty()));
}
return Optional.ofNullable(collectEnabled).orElse(true);
}
@Override
public List<MetricSample> collect() {
List<MetricSample> list = new ArrayList<>();
if (!isCollectEnabled()) {
return list;
}
list.addAll(super.export(MetricsCategory.NETTY));
return list;
}
}

View File

@ -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.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.metrics.event.TimeCounterEvent;
import org.apache.dubbo.metrics.model.key.MetricsLevel;
import org.apache.dubbo.metrics.model.key.TypeWrapper;
import org.apache.dubbo.metrics.registry.collector.NettyMetricsCollector;
import org.apache.dubbo.rpc.model.ApplicationModel;
import static org.apache.dubbo.metrics.MetricsConstants.NETTY_METRICS_MAP;
/**
* Netty related events
*/
public class NettyEvent extends TimeCounterEvent {
public NettyEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
super(applicationModel,typeWrapper);
ScopeBeanFactory beanFactory = getSource().getBeanFactory();
NettyMetricsCollector collector;
if (!beanFactory.isDestroyed()) {
collector = beanFactory.getBean(NettyMetricsCollector.class);
super.setAvailable(collector != null && collector.isCollectEnabled());
}
}
public static NettyEvent toNettyEvent(ApplicationModel applicationModel) {
return new NettyEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, null,null, null)) {
@Override
public void customAfterPost(Object postResult) {
super.putAttachment(NETTY_METRICS_MAP, postResult);
}
};
}
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metrics.registry.event;
import org.apache.dubbo.metrics.event.MetricsEvent;
import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
import org.apache.dubbo.metrics.event.TimeCounterEvent;
import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.registry.collector.NettyMetricsCollector;
import java.util.Collections;
import java.util.Map;
import static org.apache.dubbo.metrics.MetricsConstants.NETTY_METRICS_MAP;
public final class NettySubDispatcher extends SimpleMetricsEventMulticaster {
public NettySubDispatcher(NettyMetricsCollector collector) {
super.addListener(new AbstractMetricsKeyListener(null) {
@Override
public boolean isSupport(MetricsEvent event) {
return true;
}
@Override
public void onEventFinish(TimeCounterEvent event) {
Map<String, Long> lastNumMap = Collections.unmodifiableMap(event.getAttachmentValue(NETTY_METRICS_MAP));
lastNumMap.forEach(
(k, v) -> {
MetricsKey metricsKey = MetricsKey.getMetricsByName(k);
collector.setAppNum(metricsKey, v);
});
}
});
}
}

View File

@ -0,0 +1 @@
org.apache.dubbo.metrics.registry.collector.NettyMetricsCollector

View File

@ -80,7 +80,7 @@ class PrometheusMetricsReporterTest {
Double d2 = prometheusRegistry.getPrometheusRegistry().getSampleValue("jvm_gc_memory_promoted_bytes_total",
new String[]{"application_name"}, new String[]{name});
Assertions.assertNull(d1);
Assertions.assertNotNull(d2);
Assertions.assertNull(d2);
}
@Test

View File

@ -23,6 +23,7 @@ import org.apache.dubbo.metrics.model.key.MetricsLevel;
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.apache.dubbo.metrics.model.key.MetricsKey.DIRECTORY_METRIC_NUM_ALL;
@ -46,17 +47,23 @@ import static org.apache.dubbo.metrics.model.key.MetricsKey.SUBSCRIBE_METRIC_NUM
public interface RegistryMetricsConstants {
String ATTACHMENT_REGISTRY_KEY = "registryKey";
String ATTACHMENT_REGISTRY_SINGLE_KEY = "registrySingleKey";
MetricsPlaceValue OP_TYPE_REGISTER = MetricsPlaceValue.of("register", MetricsLevel.APP);
MetricsPlaceValue OP_TYPE_SUBSCRIBE = MetricsPlaceValue.of("subscribe", MetricsLevel.APP);
MetricsPlaceValue OP_TYPE_NOTIFY = MetricsPlaceValue.of("notify", MetricsLevel.APP);
MetricsPlaceValue OP_TYPE_DIRECTORY = MetricsPlaceValue.of("directory", MetricsLevel.APP);
MetricsPlaceValue OP_TYPE_REGISTER_SERVICE = MetricsPlaceValue.of("register.service", MetricsLevel.SERVICE);
MetricsPlaceValue OP_TYPE_REGISTER_SERVICE = MetricsPlaceValue.of("register.service", MetricsLevel.REGISTRY);
MetricsPlaceValue OP_TYPE_SUBSCRIBE_SERVICE = MetricsPlaceValue.of("subscribe.service", MetricsLevel.SERVICE);
// App-level
List<MetricsKey> APP_LEVEL_KEYS = Arrays.asList(REGISTER_METRIC_REQUESTS, REGISTER_METRIC_REQUESTS_SUCCEED, REGISTER_METRIC_REQUESTS_FAILED,
SUBSCRIBE_METRIC_NUM, SUBSCRIBE_METRIC_NUM_SUCCEED, SUBSCRIBE_METRIC_NUM_FAILED,
NOTIFY_METRIC_REQUESTS);
List<MetricsKey> APP_LEVEL_KEYS = Collections.singletonList(NOTIFY_METRIC_REQUESTS);
// Registry-level
List<MetricsKey> REGISTER_LEVEL_KEYS = Arrays.asList(REGISTER_METRIC_REQUESTS, REGISTER_METRIC_REQUESTS_SUCCEED, REGISTER_METRIC_REQUESTS_FAILED,
SUBSCRIBE_METRIC_NUM, SUBSCRIBE_METRIC_NUM_SUCCEED, SUBSCRIBE_METRIC_NUM_FAILED
);
// Service-level
List<MetricsKeyWrapper> SERVICE_LEVEL_KEYS = Arrays.asList(

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.metrics.registry.collector;
import org.apache.dubbo.common.constants.RegistryConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.metrics.collector.CombMetricsCollector;
@ -25,7 +26,11 @@ import org.apache.dubbo.metrics.data.ApplicationStatComposite;
import org.apache.dubbo.metrics.data.BaseStatComposite;
import org.apache.dubbo.metrics.data.RtStatComposite;
import org.apache.dubbo.metrics.data.ServiceStatComposite;
import org.apache.dubbo.metrics.model.ApplicationMetric;
import org.apache.dubbo.metrics.model.MetricsCategory;
import org.apache.dubbo.metrics.model.ServiceKeyMetric;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
@ -33,7 +38,9 @@ import org.apache.dubbo.metrics.registry.event.RegistrySubDispatcher;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_NOTIFY;
@ -51,6 +58,7 @@ public class RegistryMetricsCollector extends CombMetricsCollector<RegistryEvent
private Boolean collectEnabled = null;
private final ApplicationModel applicationModel;
private final RegistryStatComposite internalStat;
public RegistryMetricsCollector(ApplicationModel applicationModel) {
super(new BaseStatComposite(applicationModel) {
@ -73,6 +81,7 @@ public class RegistryMetricsCollector extends CombMetricsCollector<RegistryEvent
}
});
super.setEventMulticaster(new RegistrySubDispatcher(this));
internalStat = new RegistryStatComposite(applicationModel);
this.applicationModel = applicationModel;
}
@ -99,7 +108,45 @@ public class RegistryMetricsCollector extends CombMetricsCollector<RegistryEvent
return list;
}
list.addAll(super.export(MetricsCategory.REGISTRY));
list.addAll(internalStat.export(MetricsCategory.REGISTRY));
return list;
}
public void incrMetricsNum(MetricsKey metricsKey, List<String> registryClusterNames) {
registryClusterNames.forEach(name -> internalStat.incrMetricsNum(metricsKey, name));
}
public void incrRegisterFinishNum(MetricsKey metricsKey, String registryOpType, List<String> registryClusterNames, Long responseTime) {
registryClusterNames.forEach(name ->
{
ApplicationMetric applicationMetric = new ApplicationMetric(applicationModel);
applicationMetric.setExtraInfo(Collections.singletonMap(RegistryConstants.REGISTRY_CLUSTER_KEY.toLowerCase(), name));
internalStat.incrMetricsNum(metricsKey, name);
getStats().getRtStatComposite().calcServiceKeyRt(registryOpType, responseTime, applicationMetric);
});
}
public void incrServiceRegisterNum(MetricsKeyWrapper wrapper, String serviceKey, List<String> registryClusterNames, int size) {
registryClusterNames.forEach(name ->
stats.incrementServiceKey(wrapper, serviceKey, Collections.singletonMap(RegistryConstants.REGISTRY_CLUSTER_KEY.toLowerCase(), name), size)
);
}
public void incrServiceRegisterFinishNum(MetricsKeyWrapper wrapper, String serviceKey, List<String> registryClusterNames, int size, Long responseTime) {
registryClusterNames.forEach(name ->
{
Map<String, String> extraInfo = Collections.singletonMap(RegistryConstants.REGISTRY_CLUSTER_KEY.toLowerCase(), name);
ServiceKeyMetric serviceKeyMetric = new ServiceKeyMetric(applicationModel, serviceKey);
serviceKeyMetric.setExtraInfo(extraInfo);
stats.incrementServiceKey(wrapper, serviceKey, extraInfo, size);
getStats().getRtStatComposite().calcServiceKeyRt(wrapper.getType(), responseTime, serviceKeyMetric);
}
);
}
public void setNum(MetricsKeyWrapper metricsKey, String serviceKey, int num, Map<String, String> attachments) {
this.stats.setServiceKey(metricsKey, serviceKey, num, attachments);
}
}

View File

@ -0,0 +1,81 @@
/*
* 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.constants.RegistryConstants;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.metrics.model.ApplicationMetric;
import org.apache.dubbo.metrics.model.MetricsCategory;
import org.apache.dubbo.metrics.model.MetricsSupport;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
import org.apache.dubbo.metrics.report.AbstractMetricsExport;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE;
public class RegistryStatComposite extends AbstractMetricsExport {
private final Map<MetricsKey, Map<ApplicationMetric, AtomicLong>> appStats = new ConcurrentHashMap<>();
public RegistryStatComposite(ApplicationModel applicationModel) {
super(applicationModel);
init(RegistryMetricsConstants.REGISTER_LEVEL_KEYS);
}
public void init(List<MetricsKey> appKeys) {
if (CollectionUtils.isEmpty(appKeys)) {
return;
}
appKeys.forEach(appKey -> appStats.put(appKey, new ConcurrentHashMap<>()));
}
@Override
public List<MetricSample> export(MetricsCategory category) {
List<MetricSample> list = new ArrayList<>();
for (MetricsKey metricsKey : appStats.keySet()) {
Map<ApplicationMetric, AtomicLong> stringAtomicLongMap = appStats.get(metricsKey);
for (ApplicationMetric registerKeyMetric : stringAtomicLongMap.keySet()) {
list.add(new GaugeMetricSample<>(metricsKey, registerKeyMetric.getTags(), category, stringAtomicLongMap, value -> value.get(registerKeyMetric).get()));
}
}
return list;
}
public void incrMetricsNum(MetricsKey metricsKey, String name) {
if (!appStats.containsKey(metricsKey)) {
return;
}
ApplicationMetric applicationMetric = new ApplicationMetric(getApplicationModel());
applicationMetric.setExtraInfo(Collections.singletonMap(RegistryConstants.REGISTRY_CLUSTER_KEY.toLowerCase(), name));
appStats.get(metricsKey).computeIfAbsent(applicationMetric, k -> new AtomicLong(0L)).getAndAdd(SELF_INCREMENT_SIZE);
MetricsSupport.fillZero(appStats);
}
public Map<MetricsKey, Map<ApplicationMetric, AtomicLong>> getAppStats() {
return appStats;
}
}

View File

@ -22,9 +22,12 @@ import org.apache.dubbo.metrics.event.TimeCounterEvent;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsLevel;
import org.apache.dubbo.metrics.model.key.TypeWrapper;
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_DIRECTORY_MAP;
@ -48,18 +51,25 @@ public class RegistryEvent extends TimeCounterEvent {
}
private static final TypeWrapper REGISTER_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.REGISTER_METRIC_REQUESTS, MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.REGISTER_METRIC_REQUESTS_FAILED);
public static RegistryEvent toRegisterEvent(ApplicationModel applicationModel) {
return new RegistryEvent(applicationModel, REGISTER_EVENT);
public static RegistryEvent toRegisterEvent(ApplicationModel applicationModel, List<String> registryClusterNames) {
RegistryEvent registryEvent = new RegistryEvent(applicationModel, REGISTER_EVENT);
registryEvent.putAttachment(RegistryMetricsConstants.ATTACHMENT_REGISTRY_KEY, registryClusterNames);
return registryEvent;
}
private static final TypeWrapper SUBSCRIBE_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.SUBSCRIBE_METRIC_NUM, MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED);
public static RegistryEvent toSubscribeEvent(ApplicationModel applicationModel) {
return new RegistryEvent(applicationModel, SUBSCRIBE_EVENT);
public static RegistryEvent toSubscribeEvent(ApplicationModel applicationModel, String registryClusterName) {
RegistryEvent ddEvent = new RegistryEvent(applicationModel, SUBSCRIBE_EVENT);
ddEvent.putAttachment(RegistryMetricsConstants.ATTACHMENT_REGISTRY_KEY, Collections.singletonList(registryClusterName));
return ddEvent;
}
private static final TypeWrapper NOTIFY_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsKey.NOTIFY_METRIC_NUM_LAST, (MetricsKey) null);
public static RegistryEvent toNotifyEvent(ApplicationModel applicationModel) {
return new RegistryEvent(applicationModel, NOTIFY_EVENT) {
@Override
@ -70,24 +80,31 @@ public class RegistryEvent extends TimeCounterEvent {
}
private static final TypeWrapper RS_EVENT = new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED);
public static RegistryEvent toRsEvent(ApplicationModel applicationModel, String serviceKey, int size) {
public static RegistryEvent toRsEvent(ApplicationModel applicationModel, String serviceKey, int size, List<String> serviceDiscoveryNames) {
RegistryEvent ddEvent = new RegistryEvent(applicationModel, RS_EVENT);
ddEvent.putAttachment(ATTACHMENT_KEY_SERVICE, serviceKey);
ddEvent.putAttachment(ATTACHMENT_KEY_SIZE, size);
ddEvent.putAttachment(RegistryMetricsConstants.ATTACHMENT_REGISTRY_KEY, serviceDiscoveryNames);
return ddEvent;
}
private static final TypeWrapper SS_EVENT = new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_FAILED);
public static RegistryEvent toSsEvent(ApplicationModel applicationModel, String serviceKey) {
public static RegistryEvent toSsEvent(ApplicationModel applicationModel, String serviceKey, List<String> serviceDiscoveryNames) {
RegistryEvent ddEvent = new RegistryEvent(applicationModel, SS_EVENT);
ddEvent.putAttachment(ATTACHMENT_KEY_SERVICE, serviceKey);
ddEvent.putAttachment(ATTACHMENT_KEY_SIZE, 1);
ddEvent.putAttachment(RegistryMetricsConstants.ATTACHMENT_REGISTRY_KEY, serviceDiscoveryNames);
return ddEvent;
}
private static final TypeWrapper DIRECTORY_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.DIRECTORY_METRIC_NUM_VALID, null, null);
public static RegistryEvent refreshDirectoryEvent(ApplicationModel applicationModel, Map<MetricsKey, Map<String, Integer>> summaryMap) {
public static RegistryEvent refreshDirectoryEvent(ApplicationModel applicationModel, Map<MetricsKey, Map<String, Integer>> summaryMap, Map<String, String> attachments) {
RegistryEvent registryEvent = new RegistryEvent(applicationModel, DIRECTORY_EVENT);
registryEvent.putAttachment(ATTACHMENT_DIRECTORY_MAP, summaryMap);
registryEvent.putAttachments(attachments);
return registryEvent;
}

View File

@ -0,0 +1,154 @@
/*
* 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.utils.CollectionUtils;
import org.apache.dubbo.metrics.collector.CombMetricsCollector;
import org.apache.dubbo.metrics.event.MetricsEvent;
import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener;
import org.apache.dubbo.metrics.listener.MetricsApplicationListener;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_DIRECTORY_MAP;
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_LAST_NUM_MAP;
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SIZE;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_DIRECTORY;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_NOTIFY;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_REGISTER;
/**
* Different from the general-purpose listener constructor {@link MetricsApplicationListener} ,
* it provides registry custom listeners
*/
public class RegistrySpecListener {
/**
* Perform auto-increment on the monitored key,
* Can use a custom listener instead of this generic operation
*/
public static AbstractMetricsKeyListener onPost(MetricsKey metricsKey, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onEvent(metricsKey,
event -> ((RegistryMetricsCollector) collector).incrMetricsNum(metricsKey, getRgs(event))
);
}
public static AbstractMetricsKeyListener onFinish(MetricsKey metricsKey, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onFinish(metricsKey,
event -> ((RegistryMetricsCollector) collector).incrRegisterFinishNum(metricsKey, OP_TYPE_REGISTER.getType(), getRgs(event), event.getTimePair().calc())
);
}
public static AbstractMetricsKeyListener onError(MetricsKey metricsKey, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onError(metricsKey,
event -> ((RegistryMetricsCollector) collector).incrRegisterFinishNum(metricsKey, OP_TYPE_REGISTER.getType(), getRgs(event), event.getTimePair().calc())
);
}
public static AbstractMetricsKeyListener onPostOfService(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onEvent(metricsKey,
event -> ((RegistryMetricsCollector) collector).incrServiceRegisterNum(new MetricsKeyWrapper(metricsKey, placeType), getServiceKey(event), getRgs(event), getSize(event))
);
}
public static AbstractMetricsKeyListener onFinishOfService(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onFinish(metricsKey,
event -> ((RegistryMetricsCollector) collector).incrServiceRegisterFinishNum(new MetricsKeyWrapper(metricsKey, placeType), getServiceKey(event), getRgs(event), getSize(event), event.getTimePair().calc())
);
}
public static AbstractMetricsKeyListener onErrorOfService(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onError(metricsKey,
event -> ((RegistryMetricsCollector) collector).incrServiceRegisterFinishNum(new MetricsKeyWrapper(metricsKey, placeType), getServiceKey(event), getRgs(event), getSize(event), event.getTimePair().calc())
);
}
/**
* Every time an event is triggered, multiple serviceKey related to notify are increment
*/
public static AbstractMetricsKeyListener onFinishOfNotify(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onFinish(metricsKey,
event ->
{
collector.addServiceRt(event.appName(), placeType.getType(), event.getTimePair().calc());
Map<String, Integer> lastNumMap = Collections.unmodifiableMap(event.getAttachmentValue(ATTACHMENT_KEY_LAST_NUM_MAP));
lastNumMap.forEach(
(k, v) -> collector.setNum(new MetricsKeyWrapper(metricsKey, OP_TYPE_NOTIFY), k, v));
}
);
}
/**
* Every time an event is triggered, multiple fixed key related to directory are increment, which has nothing to do with the monitored key
*/
public static AbstractMetricsKeyListener onPostOfDirectory(MetricsKey metricsKey, CombMetricsCollector<?> collector) {
return AbstractMetricsKeyListener.onEvent(metricsKey,
event -> {
Map<MetricsKey, Map<String, Integer>> summaryMap = event.getAttachmentValue(ATTACHMENT_DIRECTORY_MAP);
Map<String, String> otherAttachments = new HashMap<>();
for (Map.Entry<String, Object> entry : event.getAttachments().entrySet()) {
if (entry.getValue() instanceof String) {
otherAttachments.put(entry.getKey().toLowerCase(Locale.ROOT), (String) entry.getValue());
}
}
summaryMap.forEach((summaryKey, map) ->
map.forEach(
(k, v) ->
{
if (CollectionUtils.isEmptyMap(otherAttachments)) {
collector.setNum(new MetricsKeyWrapper(summaryKey, OP_TYPE_DIRECTORY), k, v);
} else {
((RegistryMetricsCollector) collector).setNum(new MetricsKeyWrapper(summaryKey, OP_TYPE_DIRECTORY), k, v, otherAttachments);
}
}
));
}
);
}
/**
* Get the number of multiple registries
*/
public static List<String> getRgs(MetricsEvent event) {
return event.getAttachmentValue(RegistryMetricsConstants.ATTACHMENT_REGISTRY_KEY);
}
/**
* Get the exposed number of the protocol
*/
public static int getSize(MetricsEvent event) {
return event.getAttachmentValue(ATTACHMENT_KEY_SIZE);
}
public static String getServiceKey(MetricsEvent event) {
return event.getAttachmentValue(ATTACHMENT_KEY_SERVICE);
}
}

View File

@ -18,22 +18,15 @@
package org.apache.dubbo.metrics.registry.event;
import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener;
import org.apache.dubbo.metrics.listener.MetricsApplicationListener;
import org.apache.dubbo.metrics.listener.MetricsServiceListener;
import org.apache.dubbo.metrics.model.key.CategoryOverall;
import org.apache.dubbo.metrics.model.key.MetricsCat;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_DIRECTORY_MAP;
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_LAST_NUM_MAP;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_DIRECTORY;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_NOTIFY;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_REGISTER;
@ -74,55 +67,37 @@ public final class RegistrySubDispatcher extends SimpleMetricsEventMulticaster {
/**
* {@link MetricsCat} MetricsCat collection, for better classification processing
* Except for a few custom functions, most of them can build standard event listening functions through the static methods of MetricsApplicationListener
* {@link MetricsCat} MetricsCat collection, for better classification processing
* Except for a few custom functions, most of them can build standard event listening functions through the static methods of MetricsApplicationListener
*/
interface MCat {
// MetricsRegisterListener
MetricsCat APPLICATION_REGISTER_POST = new MetricsCat(MetricsKey.REGISTER_METRIC_REQUESTS, MetricsApplicationListener::onPostEventBuild);
MetricsCat APPLICATION_REGISTER_FINISH = new MetricsCat(MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED, MetricsApplicationListener::onFinishEventBuild);
MetricsCat APPLICATION_REGISTER_ERROR = new MetricsCat(MetricsKey.REGISTER_METRIC_REQUESTS_FAILED, MetricsApplicationListener::onErrorEventBuild);
MetricsCat APPLICATION_REGISTER_POST = new MetricsCat(MetricsKey.REGISTER_METRIC_REQUESTS, RegistrySpecListener::onPost);
MetricsCat APPLICATION_REGISTER_FINISH = new MetricsCat(MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED, RegistrySpecListener::onFinish);
MetricsCat APPLICATION_REGISTER_ERROR = new MetricsCat(MetricsKey.REGISTER_METRIC_REQUESTS_FAILED, RegistrySpecListener::onError);
// MetricsSubscribeListener
MetricsCat APPLICATION_SUBSCRIBE_POST = new MetricsCat(MetricsKey.SUBSCRIBE_METRIC_NUM, MetricsApplicationListener::onPostEventBuild);
MetricsCat APPLICATION_SUBSCRIBE_FINISH = new MetricsCat(MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsApplicationListener::onFinishEventBuild);
MetricsCat APPLICATION_SUBSCRIBE_ERROR = new MetricsCat(MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED, MetricsApplicationListener::onErrorEventBuild);
MetricsCat APPLICATION_SUBSCRIBE_POST = new MetricsCat(MetricsKey.SUBSCRIBE_METRIC_NUM, RegistrySpecListener::onPost);
MetricsCat APPLICATION_SUBSCRIBE_FINISH = new MetricsCat(MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED, RegistrySpecListener::onFinish);
MetricsCat APPLICATION_SUBSCRIBE_ERROR = new MetricsCat(MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED, RegistrySpecListener::onError);
// MetricsNotifyListener
MetricsCat APPLICATION_NOTIFY_POST = new MetricsCat(MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsApplicationListener::onPostEventBuild);
MetricsCat APPLICATION_NOTIFY_FINISH = new MetricsCat(MetricsKey.NOTIFY_METRIC_NUM_LAST,
(key, placeType, collector) -> AbstractMetricsKeyListener.onFinish(key,
event -> {
collector.addServiceRt(event.appName(), placeType.getType(), event.getTimePair().calc());
Map<String, Integer> lastNumMap = Collections.unmodifiableMap(event.getAttachmentValue(ATTACHMENT_KEY_LAST_NUM_MAP));
lastNumMap.forEach(
(k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_NOTIFY), k, v));
MetricsCat APPLICATION_NOTIFY_FINISH = new MetricsCat(MetricsKey.NOTIFY_METRIC_NUM_LAST, RegistrySpecListener::onFinishOfNotify);
}
));
MetricsCat APPLICATION_DIRECTORY_POST = new MetricsCat(MetricsKey.DIRECTORY_METRIC_NUM_VALID, (key, placeType, collector) -> AbstractMetricsKeyListener.onEvent(key,
event ->
{
Map<MetricsKey, Map<String, Integer>> summaryMap = event.getAttachmentValue(ATTACHMENT_DIRECTORY_MAP);
summaryMap.forEach((metricsKey, map) ->
map.forEach(
(k, v) -> collector.setNum(new MetricsKeyWrapper(metricsKey, OP_TYPE_DIRECTORY), k, v)));
}
));
MetricsCat APPLICATION_DIRECTORY_POST = new MetricsCat(MetricsKey.DIRECTORY_METRIC_NUM_VALID, RegistrySpecListener::onPostOfDirectory);
// MetricsServiceRegisterListener
MetricsCat SERVICE_REGISTER_POST = new MetricsCat(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS, MetricsServiceListener::onPostEventBuild);
MetricsCat SERVICE_REGISTER_FINISH = new MetricsCat(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, MetricsServiceListener::onFinishEventBuild);
MetricsCat SERVICE_REGISTER_ERROR = new MetricsCat(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED, MetricsServiceListener::onErrorEventBuild);
MetricsCat SERVICE_REGISTER_POST = new MetricsCat(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS, RegistrySpecListener::onPostOfService);
MetricsCat SERVICE_REGISTER_FINISH = new MetricsCat(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, RegistrySpecListener::onFinishOfService);
MetricsCat SERVICE_REGISTER_ERROR = new MetricsCat(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED, RegistrySpecListener::onErrorOfService);
// MetricsServiceSubscribeListener
MetricsCat SERVICE_SUBSCRIBE_POST = new MetricsCat(MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM, MetricsServiceListener::onPostEventBuild);
MetricsCat SERVICE_SUBSCRIBE_FINISH = new MetricsCat(MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsServiceListener::onFinishEventBuild);
MetricsCat SERVICE_SUBSCRIBE_ERROR = new MetricsCat(MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_FAILED, MetricsServiceListener::onErrorEventBuild);
MetricsCat SERVICE_SUBSCRIBE_POST = new MetricsCat(MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM, RegistrySpecListener::onPostOfService);
MetricsCat SERVICE_SUBSCRIBE_FINISH = new MetricsCat(MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, RegistrySpecListener::onFinishOfService);
MetricsCat SERVICE_SUBSCRIBE_ERROR = new MetricsCat(MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_FAILED, RegistrySpecListener::onErrorOfService);
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.metrics.registry.metrics.collector;
import com.google.common.collect.Lists;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metrics.event.MetricsDispatcher;
import org.apache.dubbo.metrics.event.MetricsEventBus;
@ -30,12 +31,12 @@ 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.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -43,9 +44,11 @@ import java.util.Objects;
import java.util.stream.Collectors;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.APP_LEVEL_KEYS;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_REGISTER;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_SUBSCRIBE_SERVICE;
import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.REGISTER_LEVEL_KEYS;
class RegistryMetricsCollectorTest {
@ -74,12 +77,12 @@ class RegistryMetricsCollectorTest {
@Test
void testRegisterMetrics() {
RegistryEvent registryEvent = RegistryEvent.toRegisterEvent(applicationModel);
RegistryEvent registryEvent = RegistryEvent.toRegisterEvent(applicationModel, Lists.newArrayList("reg1"));
MetricsEventBus.post(registryEvent,
() -> {
List<MetricSample> metricSamples = collector.collect();
// push success +1 -> other default 0 = RegistryMetricsConstants.APP_LEVEL_KEYS.size()
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size(), metricSamples.size());
// push success +1 -> other default 0 = APP_LEVEL_KEYS.size()
Assertions.assertEquals(APP_LEVEL_KEYS.size() + REGISTER_LEVEL_KEYS.size(), metricSamples.size());
Assertions.assertTrue(metricSamples.stream().allMatch(metricSample -> metricSample instanceof GaugeMetricSample));
Assertions.assertTrue(metricSamples.stream().anyMatch(metricSample -> ((GaugeMetricSample) metricSample).applyAsDouble() == 1));
return null;
@ -88,12 +91,12 @@ class RegistryMetricsCollectorTest {
// push finish rt +1
List<MetricSample> metricSamples = collector.collect();
// RegistryMetricsConstants.APP_LEVEL_KEYS.size() + rt(5) = 12
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5, metricSamples.size());
// APP_LEVEL_KEYS.size() + rt(5) = 12
Assertions.assertEquals(APP_LEVEL_KEYS.size() + REGISTER_LEVEL_KEYS.size() + 5, metricSamples.size());
long c1 = registryEvent.getTimePair().calc();
registryEvent = RegistryEvent.toRegisterEvent(applicationModel);
registryEvent = RegistryEvent.toRegisterEvent(applicationModel, Lists.newArrayList("reg1"));
TimePair lastTimePair = registryEvent.getTimePair();
MetricsEventBus.post(registryEvent,
() -> {
@ -111,7 +114,7 @@ class RegistryMetricsCollectorTest {
metricSamples = collector.collect();
// num(total+success+error) + rt(5)
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5, metricSamples.size());
Assertions.assertEquals(APP_LEVEL_KEYS.size() + REGISTER_LEVEL_KEYS.size() + 5, metricSamples.size());
// calc rt
for (MetricSample sample : metricSamples) {
@ -134,8 +137,9 @@ class RegistryMetricsCollectorTest {
void testServicePushMetrics() {
String serviceName = "demo.gameService";
List<String> rcNames = Lists.newArrayList("demo1");
RegistryEvent registryEvent = RegistryEvent.toRsEvent(applicationModel, serviceName, 2);
RegistryEvent registryEvent = RegistryEvent.toRsEvent(applicationModel, serviceName, 2, rcNames);
MetricsEventBus.post(registryEvent,
() -> {
List<MetricSample> metricSamples = collector.collect();
@ -154,7 +158,7 @@ class RegistryMetricsCollectorTest {
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5 + 2, metricSamples.size());
long c1 = registryEvent.getTimePair().calc();
registryEvent = RegistryEvent.toRsEvent(applicationModel, serviceName, 2);
registryEvent = RegistryEvent.toRsEvent(applicationModel, serviceName, 2, rcNames);
TimePair lastTimePair = registryEvent.getTimePair();
MetricsEventBus.post(registryEvent,
() -> {
@ -196,7 +200,7 @@ class RegistryMetricsCollectorTest {
String serviceName = "demo.gameService";
RegistryEvent subscribeEvent = RegistryEvent.toSsEvent(applicationModel, serviceName);
RegistryEvent subscribeEvent = RegistryEvent.toSsEvent(applicationModel, serviceName, Collections.singletonList("demo1"));
MetricsEventBus.post(subscribeEvent,
() -> {
List<MetricSample> metricSamples = collector.collect();
@ -216,7 +220,7 @@ class RegistryMetricsCollectorTest {
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5 + 2, metricSamples.size());
long c1 = subscribeEvent.getTimePair().calc();
subscribeEvent = RegistryEvent.toSsEvent(applicationModel, serviceName);
subscribeEvent = RegistryEvent.toSsEvent(applicationModel, serviceName, Collections.singletonList("demo1"));
TimePair lastTimePair = subscribeEvent.getTimePair();
MetricsEventBus.post(subscribeEvent,
() -> {

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.metrics.registry.metrics.collector;
import com.google.common.collect.Lists;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MetricsConfig;
import org.apache.dubbo.config.context.ConfigManager;
@ -24,11 +25,11 @@ import org.apache.dubbo.config.nested.AggregationConfig;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
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.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -221,9 +222,9 @@ public class RegistryMetricsTest {
}
List<MetricSample> samples = collector.collect();
GaugeMetricSample<?> succeedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED.getName(), samples);
GaugeMetricSample<?> failedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED.getName(), samples);
GaugeMetricSample<?> totalRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS.getName(), samples);
GaugeMetricSample<?> succeedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED.getNameByType(RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE.getType()), samples);
GaugeMetricSample<?> failedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED.getNameByType(RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE.getType()), samples);
GaugeMetricSample<?> totalRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS.getNameByType(RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE.getType()), samples);
Assertions.assertEquals(5L, succeedRequests.applyAsLong());
Assertions.assertEquals(5L, failedRequests.applyAsLong());
@ -289,19 +290,20 @@ public class RegistryMetricsTest {
}
RegistryEvent registerEvent() {
RegistryEvent event = RegistryEvent.toRegisterEvent(applicationModel);
RegistryEvent event = RegistryEvent.toRegisterEvent(applicationModel, Lists.newArrayList("reg1"));
event.setAvailable(true);
return event;
}
RegistryEvent rsEvent() {
RegistryEvent event = RegistryEvent.toRsEvent(applicationModel, "TestServiceInterface1", 1);
List<String> rcNames = Lists.newArrayList("demo1");
RegistryEvent event = RegistryEvent.toRsEvent(applicationModel, "TestServiceInterface1", 1, rcNames);
event.setAvailable(true);
return event;
}
RegistryEvent subscribeEvent() {
RegistryEvent event = RegistryEvent.toSubscribeEvent(applicationModel);
RegistryEvent event = RegistryEvent.toSubscribeEvent(applicationModel, "registryClusterName_test");
event.setAvailable(true);
return event;
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.metrics.registry.metrics.collector;
import org.apache.dubbo.common.constants.RegistryConstants;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metrics.data.ApplicationStatComposite;
import org.apache.dubbo.metrics.data.BaseStatComposite;
@ -29,12 +30,15 @@ import org.apache.dubbo.metrics.model.container.LongContainer;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
import org.apache.dubbo.metrics.registry.collector.RegistryStatComposite;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -55,6 +59,7 @@ public class RegistryStatCompositeTest {
private ApplicationModel applicationModel;
private String applicationName;
private BaseStatComposite statComposite;
private RegistryStatComposite regStatComposite;
@BeforeEach
public void setup() {
@ -83,6 +88,7 @@ public class RegistryStatCompositeTest {
rtStatComposite.init(OP_TYPE_REGISTER, OP_TYPE_SUBSCRIBE, OP_TYPE_NOTIFY, OP_TYPE_REGISTER_SERVICE, OP_TYPE_SUBSCRIBE_SERVICE);
}
};
regStatComposite = new RegistryStatComposite(applicationModel);
}
@Test
@ -102,8 +108,10 @@ public class RegistryStatCompositeTest {
@Test
void testIncrement() {
statComposite.incrementApp(REGISTER_METRIC_REQUESTS, 1);
Assertions.assertEquals(1L, statComposite.getApplicationStatComposite().getApplicationNumStats().get(REGISTER_METRIC_REQUESTS).get());
regStatComposite.incrMetricsNum(REGISTER_METRIC_REQUESTS, "beijing");
ApplicationMetric applicationMetric = new ApplicationMetric(applicationModel);
applicationMetric.setExtraInfo(Collections.singletonMap(RegistryConstants.REGISTRY_CLUSTER_KEY.toLowerCase(), "beijing"));
Assertions.assertEquals(1L, regStatComposite.getAppStats().get(REGISTER_METRIC_REQUESTS).get(applicationMetric).get());
}
@Test

View File

@ -107,5 +107,12 @@
<artifactId>zipkin-reporter-brave</artifactId>
<optional>true</optional>
</dependency>
<!-- sender -->
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-urlconnection</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -1,66 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.tracing.exporter;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.otlp.OTlpExporter;
import org.apache.dubbo.tracing.exporter.zipkin.ZipkinExporter;
import brave.handler.SpanHandler;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.ArrayList;
import java.util.List;
public class TraceExporterFactory {
private final static ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(TraceExporterFactory.class);
/**
* for OTel
*/
public static List<SpanExporter> getSpanExporters(ApplicationModel applicationModel, ExporterConfig exporterConfig) {
ExporterConfig.ZipkinConfig zipkinConfig = exporterConfig.getZipkinConfig();
ExporterConfig.OtlpConfig otlpConfig = exporterConfig.getOtlpConfig();
List<SpanExporter> res = new ArrayList<>();
if (zipkinConfig != null && StringUtils.isNotEmpty(zipkinConfig.getEndpoint())) {
ZipkinExporter zipkinExporter = new ZipkinExporter(applicationModel, zipkinConfig);
LOGGER.info("Create zipkin span exporter.");
res.add(zipkinExporter.getSpanExporter());
}
if (otlpConfig != null && StringUtils.isNotEmpty(otlpConfig.getEndpoint())) {
OTlpExporter otlpExporter = new OTlpExporter(applicationModel, otlpConfig);
LOGGER.info("Create OTlp span exporter.");
res.add(otlpExporter.getSpanExporter());
}
return res;
}
/**
* for Brave
*/
public static List<SpanHandler> getSpanHandlers(ApplicationModel applicationModel, ExporterConfig exporterConfig) {
List<SpanHandler> res = new ArrayList<>();
// TODO brave SpanHandler impl
return res;
}
}

View File

@ -18,9 +18,7 @@ package org.apache.dubbo.tracing.exporter.otlp;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.TraceExporter;
import brave.handler.SpanHandler;
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
@ -28,18 +26,12 @@ import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.Map;
public class OTlpExporter implements TraceExporter {
/**
* OTlp span exporter for OTel.
*/
public class OTlpSpanExporter {
private final ApplicationModel applicationModel;
private final ExporterConfig.OtlpConfig otlpConfig;
public OTlpExporter(ApplicationModel applicationModel, ExporterConfig.OtlpConfig otlpConfig) {
this.applicationModel = applicationModel;
this.otlpConfig = otlpConfig;
}
@Override
public SpanExporter getSpanExporter() {
public static SpanExporter getSpanExporter(ApplicationModel applicationModel, ExporterConfig.OtlpConfig otlpConfig) {
OtlpGrpcSpanExporter externalOTlpGrpcSpanExporter = applicationModel.getBeanFactory().getBean(OtlpGrpcSpanExporter.class);
if (externalOTlpGrpcSpanExporter != null) {
return externalOTlpGrpcSpanExporter;
@ -57,10 +49,4 @@ public class OTlpExporter implements TraceExporter {
}
return builder.build();
}
@Override
public SpanHandler getSpanHandler() {
// OTlp is only belong to OTel.
return null;
}
}

View File

@ -18,43 +18,26 @@ package org.apache.dubbo.tracing.exporter.zipkin;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.TraceExporter;
import brave.handler.SpanHandler;
import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import zipkin2.Span;
import zipkin2.codec.BytesEncoder;
import zipkin2.codec.SpanBytesEncoder;
public class ZipkinExporter implements TraceExporter {
/**
* Zipkin span exporter for OTel.
*/
public class ZipkinSpanExporter {
private final ApplicationModel applicationModel;
private final ExporterConfig.ZipkinConfig zipkinConfig;
public ZipkinExporter(ApplicationModel applicationModel, ExporterConfig.ZipkinConfig zipkinConfig) {
this.applicationModel = applicationModel;
this.zipkinConfig = zipkinConfig;
}
@Override
public SpanExporter getSpanExporter() {
BytesEncoder<Span> encoder = getSpanBytesEncoder();
return ZipkinSpanExporter.builder()
.setEncoder(encoder)
public static io.opentelemetry.sdk.trace.export.SpanExporter getSpanExporter(ApplicationModel applicationModel, ExporterConfig.ZipkinConfig zipkinConfig) {
return io.opentelemetry.exporter.zipkin.ZipkinSpanExporter.builder()
.setEncoder(getSpanBytesEncoder(applicationModel))
.setEndpoint(zipkinConfig.getEndpoint())
.setReadTimeout(zipkinConfig.getReadTimeout())
.build();
}
@Override
public SpanHandler getSpanHandler() {
// TODO SpanHandler of Brave impl
return null;
}
private BytesEncoder<Span> getSpanBytesEncoder() {
BytesEncoder<Span> encoder = applicationModel.getBeanFactory().getBean(BytesEncoder.class);
private static BytesEncoder<Span> getSpanBytesEncoder(ApplicationModel applicationModel) {
BytesEncoder<zipkin2.Span> encoder = applicationModel.getBeanFactory().getBean(BytesEncoder.class);
return encoder == null ? SpanBytesEncoder.JSON_V2 : encoder;
}
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.tracing.exporter.zipkin;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import brave.handler.SpanHandler;
import zipkin2.Span;
import zipkin2.codec.BytesEncoder;
import zipkin2.codec.SpanBytesEncoder;
import zipkin2.reporter.AsyncReporter;
import zipkin2.reporter.urlconnection.URLConnectionSender;
/**
* Zipkin span handler for Brave.
*/
public class ZipkinSpanHandler {
public static SpanHandler getSpanHandler(ApplicationModel applicationModel, ExporterConfig.ZipkinConfig zipkinConfig) {
URLConnectionSender sender = applicationModel.getBeanFactory().getBean(URLConnectionSender.class);
if (sender == null) {
URLConnectionSender.Builder builder = URLConnectionSender.newBuilder();
builder.connectTimeout((int) zipkinConfig.getConnectTimeout().toMillis());
builder.readTimeout((int) zipkinConfig.getReadTimeout().toMillis());
builder.endpoint(zipkinConfig.getEndpoint());
sender = builder.build();
}
AsyncReporter<Span> spanReporter = AsyncReporter.builder(sender).build(getSpanBytesEncoder(applicationModel));
return zipkin2.reporter.brave.ZipkinSpanHandler.newBuilder(spanReporter).build();
}
private static BytesEncoder<zipkin2.Span> getSpanBytesEncoder(ApplicationModel applicationModel) {
BytesEncoder<zipkin2.Span> encoder = applicationModel.getBeanFactory().getBean(BytesEncoder.class);
return encoder == null ? SpanBytesEncoder.JSON_V2 : encoder;
}
}

View File

@ -18,14 +18,20 @@ package org.apache.dubbo.tracing.tracer.brave;
import org.apache.dubbo.tracing.tracer.PropagatorProvider;
import io.micrometer.tracing.brave.bridge.BravePropagator;
import io.micrometer.tracing.propagation.Propagator;
public class BravePropagatorProvider implements PropagatorProvider {
private static Propagator propagator;
@Override
public Propagator getPropagator() {
// TODO impl
return null;
return propagator;
}
protected static void createMicrometerPropagator(brave.Tracing tracing) {
propagator = new BravePropagator(tracing);
}
}

View File

@ -16,15 +16,40 @@
*/
package org.apache.dubbo.tracing.tracer.brave;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.TracingConfig;
import org.apache.dubbo.config.nested.BaggageConfig;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.zipkin.ZipkinSpanHandler;
import org.apache.dubbo.tracing.tracer.TracerProvider;
import org.apache.dubbo.tracing.utils.PropagationType;
import io.micrometer.tracing.CurrentTraceContext;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.brave.bridge.BraveBaggageManager;
import io.micrometer.tracing.brave.bridge.BraveCurrentTraceContext;
import io.micrometer.tracing.brave.bridge.BraveTracer;
import io.micrometer.tracing.brave.bridge.W3CPropagation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.apache.dubbo.tracing.utils.ObservationConstants.DEFAULT_APPLICATION_NAME;
import static org.apache.dubbo.tracing.utils.ObservationSupportUtil.isSupportBraveURLSender;
public class BraveProvider implements TracerProvider {
private final static ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(BraveProvider.class);
private static final BraveBaggageManager BRAVE_BAGGAGE_MANAGER = new BraveBaggageManager();
private final ApplicationModel applicationModel;
private final TracingConfig tracingConfig;
@ -35,7 +60,139 @@ public class BraveProvider implements TracerProvider {
@Override
public Tracer getTracer() {
// TODO impl
return null;
// [Brave component] SpanHandler is a component that gets called when a span is finished.
List<brave.handler.SpanHandler> spanHandlerList = getSpanHandlers();
String applicationName = applicationModel.getApplicationConfigManager().getApplication()
.map(ApplicationConfig::getName)
.orElse(DEFAULT_APPLICATION_NAME);
// [Brave component] CurrentTraceContext is a Brave component that allows you to
// retrieve the current TraceContext.
brave.propagation.ThreadLocalCurrentTraceContext braveCurrentTraceContext = brave.propagation.ThreadLocalCurrentTraceContext.newBuilder()
.addScopeDecorator(correlationScopeDecorator()) // Brave's automatic MDC setup
.build();
// [Micrometer Tracing component] A Micrometer Tracing wrapper for Brave's CurrentTraceContext
CurrentTraceContext bridgeContext = new BraveCurrentTraceContext(braveCurrentTraceContext);
// [Brave component] Tracing is the root component that allows to configure the
// tracer, handlers, context propagation etc.
brave.Tracing.Builder builder = brave.Tracing.newBuilder()
.currentTraceContext(braveCurrentTraceContext)
.supportsJoin(false)
.traceId128Bit(true)
.localServiceName(applicationName)
// For Baggage to work you need to provide a list of fields to propagate
.propagationFactory(PropagatorFactory.getPropagationFactory(tracingConfig))
.sampler(getSampler());
spanHandlerList.forEach(builder::addSpanHandler);
brave.Tracing tracing = builder.build();
BravePropagatorProvider.createMicrometerPropagator(tracing);
// [Brave component] Tracer is a component that handles the life-cycle of a span
brave.Tracer braveTracer = tracing.tracer();
// [Micrometer Tracing component] A Micrometer Tracing wrapper for Brave's Tracer
return new BraveTracer(braveTracer, bridgeContext, BRAVE_BAGGAGE_MANAGER);
}
private List<brave.handler.SpanHandler> getSpanHandlers() {
ExporterConfig exporterConfig = tracingConfig.getTracingExporter();
List<brave.handler.SpanHandler> res = new ArrayList<>();
if (!isSupportBraveURLSender()) {
return res;
}
ExporterConfig.ZipkinConfig zipkinConfig = exporterConfig.getZipkinConfig();
if (zipkinConfig != null && StringUtils.isNotEmpty(zipkinConfig.getEndpoint())) {
LOGGER.info("Create zipkin span handler.");
res.add(ZipkinSpanHandler.getSpanHandler(applicationModel, zipkinConfig));
}
return res;
}
private brave.sampler.Sampler getSampler() {
return brave.sampler.Sampler.create(tracingConfig.getSampling().getProbability());
}
private Optional<brave.baggage.CorrelationScopeCustomizer> correlationFieldsCorrelationScopeCustomizer() {
BaggageConfig.Correlation correlation = tracingConfig.getBaggage().getCorrelation();
boolean enabled = correlation.isEnabled();
if (!enabled) {
return Optional.empty();
}
return Optional.of((builder) -> {
List<String> correlationFields = correlation.getFields();
for (String field : correlationFields) {
builder.add(brave.baggage.CorrelationScopeConfig.SingleCorrelationField.newBuilder(brave.baggage.BaggageField.create(field))
.flushOnUpdate().build());
}
});
}
private brave.propagation.CurrentTraceContext.ScopeDecorator correlationScopeDecorator() {
brave.baggage.CorrelationScopeDecorator.Builder builder = brave.context.slf4j.MDCScopeDecorator.newBuilder();
correlationFieldsCorrelationScopeCustomizer().ifPresent((customizer) -> customizer.customize(builder));
return builder.build();
}
static class PropagatorFactory {
public static brave.propagation.Propagation.Factory getPropagationFactory(TracingConfig tracingConfig) {
BaggageConfig baggageConfig = tracingConfig.getBaggage();
if (baggageConfig == null || !baggageConfig.getEnabled()) {
return getPropagationFactoryWithoutBaggage(tracingConfig);
}
return getPropagationFactoryWithBaggage(tracingConfig);
}
private static brave.propagation.Propagation.Factory getPropagationFactoryWithoutBaggage(TracingConfig tracingConfig) {
PropagationType propagationType = PropagationType.forValue(tracingConfig.getPropagation().getType());
if (PropagationType.W3C == propagationType) {
return new io.micrometer.tracing.brave.bridge.W3CPropagation();
} else {
// Brave default propagation is B3
return brave.propagation.B3Propagation.newFactoryBuilder().injectFormat(brave.propagation.B3Propagation.Format.SINGLE_NO_PARENT).build();
}
}
private static brave.propagation.Propagation.Factory getPropagationFactoryWithBaggage(TracingConfig tracingConfig) {
PropagationType propagationType = PropagationType.forValue(tracingConfig.getPropagation().getType());
brave.propagation.Propagation.Factory delegate;
if (PropagationType.W3C == propagationType) {
delegate = new W3CPropagation(BRAVE_BAGGAGE_MANAGER, Collections.emptyList());
} else {
// Brave default propagation is B3
delegate = brave.propagation.B3Propagation.newFactoryBuilder().injectFormat(brave.propagation.B3Propagation.Format.SINGLE_NO_PARENT).build();
}
return getBaggageFactoryBuilder(delegate, tracingConfig).build();
}
private static brave.baggage.BaggagePropagation.FactoryBuilder getBaggageFactoryBuilder(brave.propagation.Propagation.Factory delegate, TracingConfig tracingConfig) {
brave.baggage.BaggagePropagation.FactoryBuilder builder = brave.baggage.BaggagePropagation.newFactoryBuilder(delegate);
getBaggagePropagationCustomizers(tracingConfig).forEach((customizer) -> customizer.customize(builder));
return builder;
}
private static List<brave.baggage.BaggagePropagationCustomizer> getBaggagePropagationCustomizers(TracingConfig tracingConfig) {
List<brave.baggage.BaggagePropagationCustomizer> res = new ArrayList<>();
if (tracingConfig.getBaggage().getCorrelation().isEnabled()) {
res.add(remoteFieldsBaggagePropagationCustomizer(tracingConfig));
}
return res;
}
private static brave.baggage.BaggagePropagationCustomizer remoteFieldsBaggagePropagationCustomizer(TracingConfig tracingConfig) {
return (builder) -> {
List<String> remoteFields = tracingConfig.getBaggage().getRemoteFields();
for (String fieldName : remoteFields) {
builder.add(brave.baggage.BaggagePropagationConfig.SingleBaggageField.remote(brave.baggage.BaggageField.create(fieldName)));
}
};
}
}
}

View File

@ -18,13 +18,19 @@ package org.apache.dubbo.tracing.tracer.otel;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.lang.Nullable;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.TracingConfig;
import org.apache.dubbo.config.nested.BaggageConfig;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.config.nested.PropagationConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.TraceExporterFactory;
import org.apache.dubbo.tracing.exporter.otlp.OTlpSpanExporter;
import org.apache.dubbo.tracing.exporter.zipkin.ZipkinSpanExporter;
import org.apache.dubbo.tracing.tracer.TracerProvider;
import org.apache.dubbo.tracing.utils.PropagationType;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.otel.bridge.CompositeSpanExporter;
@ -36,28 +42,17 @@ import io.micrometer.tracing.otel.bridge.OtelTracer;
import io.micrometer.tracing.otel.bridge.Slf4JBaggageEventListener;
import io.micrometer.tracing.otel.bridge.Slf4JEventListener;
import io.micrometer.tracing.otel.propagation.BaggageTextMapPropagator;
import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.ContextStorage;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.extension.trace.propagation.B3Propagator;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.apache.dubbo.tracing.utils.ObservationConstants.DEFAULT_APPLICATION_NAME;
public class OpenTelemetryProvider implements TracerProvider {
private static final String DEFAULT_APPLICATION_NAME = "dubbo-application";
private final static ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(OpenTelemetryProvider.class);
private final ApplicationModel applicationModel;
private final TracingConfig tracingConfig;
@ -72,7 +67,7 @@ public class OpenTelemetryProvider implements TracerProvider {
@Override
public Tracer getTracer() {
// [OTel component] SpanExporter is a component that gets called when a span is finished.
List<SpanExporter> spanExporters = TraceExporterFactory.getSpanExporters(applicationModel, tracingConfig.getTracingExporter());
List<io.opentelemetry.sdk.trace.export.SpanExporter> spanExporters = getSpanExporters();
String applicationName = applicationModel.getApplicationConfigManager().getApplication()
.map(ApplicationConfig::getName)
@ -84,18 +79,18 @@ public class OpenTelemetryProvider implements TracerProvider {
this.otelCurrentTraceContext = createCurrentTraceContext();
// [OTel component] SdkTracerProvider is an SDK implementation for TracerProvider
SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
io.opentelemetry.sdk.trace.SdkTracerProvider sdkTracerProvider = io.opentelemetry.sdk.trace.SdkTracerProvider.builder()
.setSampler(getSampler())
.setResource(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName)))
.addSpanProcessor(BatchSpanProcessor
.setResource(io.opentelemetry.sdk.resources.Resource.create(io.opentelemetry.api.common.Attributes.of(io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME, applicationName)))
.addSpanProcessor(io.opentelemetry.sdk.trace.export.BatchSpanProcessor
.builder(new CompositeSpanExporter(spanExporters, null, null, null))
.build())
.build();
ContextPropagators otelContextPropagators = createOtelContextPropagators();
io.opentelemetry.context.propagation.ContextPropagators otelContextPropagators = createOtelContextPropagators();
// [OTel component] The SDK implementation of OpenTelemetry
OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder()
io.opentelemetry.sdk.OpenTelemetrySdk openTelemetrySdk = io.opentelemetry.sdk.OpenTelemetrySdk.builder()
.setTracerProvider(sdkTracerProvider)
.setPropagators(otelContextPropagators)
.build();
@ -113,14 +108,31 @@ public class OpenTelemetryProvider implements TracerProvider {
Collections.emptyList()));
}
private List<io.opentelemetry.sdk.trace.export.SpanExporter> getSpanExporters() {
ExporterConfig exporterConfig = tracingConfig.getTracingExporter();
ExporterConfig.ZipkinConfig zipkinConfig = exporterConfig.getZipkinConfig();
ExporterConfig.OtlpConfig otlpConfig = exporterConfig.getOtlpConfig();
List<io.opentelemetry.sdk.trace.export.SpanExporter> res = new ArrayList<>();
if (zipkinConfig != null && StringUtils.isNotEmpty(zipkinConfig.getEndpoint())) {
LOGGER.info("Create zipkin span exporter.");
res.add(ZipkinSpanExporter.getSpanExporter(applicationModel, zipkinConfig));
}
if (otlpConfig != null && StringUtils.isNotEmpty(otlpConfig.getEndpoint())) {
LOGGER.info("Create OTlp span exporter.");
res.add(OTlpSpanExporter.getSpanExporter(applicationModel, otlpConfig));
}
return res;
}
/**
* sampler with probability
*
* @return sampler
*/
private Sampler getSampler() {
Sampler rootSampler = Sampler.traceIdRatioBased(tracingConfig.getSampling().getProbability());
return Sampler.parentBased(rootSampler);
private io.opentelemetry.sdk.trace.samplers.Sampler getSampler() {
io.opentelemetry.sdk.trace.samplers.Sampler rootSampler = io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(tracingConfig.getSampling().getProbability());
return io.opentelemetry.sdk.trace.samplers.Sampler.parentBased(rootSampler);
}
private List<EventListener> getEventListeners() {
@ -141,13 +153,13 @@ public class OpenTelemetryProvider implements TracerProvider {
}
private OtelCurrentTraceContext createCurrentTraceContext() {
ContextStorage.addWrapper(new EventPublishingContextWrapper(publisher));
io.opentelemetry.context.ContextStorage.addWrapper(new EventPublishingContextWrapper(publisher));
return new OtelCurrentTraceContext();
}
private ContextPropagators createOtelContextPropagators() {
return ContextPropagators.create(
TextMapPropagator.composite(
private io.opentelemetry.context.propagation.ContextPropagators createOtelContextPropagators() {
return io.opentelemetry.context.propagation.ContextPropagators.create(
io.opentelemetry.context.propagation.TextMapPropagator.composite(
PropagatorFactory.getPropagator(tracingConfig.getPropagation(),
tracingConfig.getBaggage(),
otelCurrentTraceContext
@ -172,41 +184,44 @@ public class OpenTelemetryProvider implements TracerProvider {
static class PropagatorFactory {
public static TextMapPropagator getPropagator(PropagationConfig propagationConfig,
@Nullable BaggageConfig baggageConfig,
@Nullable OtelCurrentTraceContext currentTraceContext) {
public static io.opentelemetry.context.propagation.TextMapPropagator getPropagator(PropagationConfig propagationConfig,
@Nullable BaggageConfig baggageConfig,
@Nullable OtelCurrentTraceContext currentTraceContext) {
if (baggageConfig == null || !baggageConfig.getEnabled()) {
return getPropagatorWithoutBaggage(propagationConfig);
}
return getPropagatorWithBaggage(propagationConfig, baggageConfig, currentTraceContext);
}
private static TextMapPropagator getPropagatorWithoutBaggage(PropagationConfig propagationConfig) {
private static io.opentelemetry.context.propagation.TextMapPropagator getPropagatorWithoutBaggage(PropagationConfig propagationConfig) {
String type = propagationConfig.getType();
if ("B3".equals(type)) {
return B3Propagator.injectingSingleHeader();
} else if ("W3C".equals(type)) {
return W3CTraceContextPropagator.getInstance();
PropagationType propagationType = PropagationType.forValue(type);
if (PropagationType.B3 == propagationType) {
return io.opentelemetry.extension.trace.propagation.B3Propagator.injectingSingleHeader();
} else if (PropagationType.W3C == propagationType) {
return io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator.getInstance();
}
return TextMapPropagator.noop();
return io.opentelemetry.context.propagation.TextMapPropagator.noop();
}
private static TextMapPropagator getPropagatorWithBaggage(PropagationConfig propagationConfig,
BaggageConfig baggageConfig,
OtelCurrentTraceContext currentTraceContext) {
private static io.opentelemetry.context.propagation.TextMapPropagator getPropagatorWithBaggage(PropagationConfig propagationConfig,
BaggageConfig baggageConfig,
OtelCurrentTraceContext currentTraceContext) {
String type = propagationConfig.getType();
if ("B3".equals(type)) {
PropagationType propagationType = PropagationType.forValue(type);
if (PropagationType.B3 == propagationType) {
List<String> remoteFields = baggageConfig.getRemoteFields();
return TextMapPropagator.composite(B3Propagator.injectingSingleHeader(),
return io.opentelemetry.context.propagation.TextMapPropagator.composite(io.opentelemetry.extension.trace.propagation.B3Propagator.injectingSingleHeader(),
new BaggageTextMapPropagator(remoteFields,
new OtelBaggageManager(currentTraceContext, remoteFields, Collections.emptyList())));
} else if ("W3C".equals(type)) {
} else if (PropagationType.W3C == propagationType) {
List<String> remoteFields = baggageConfig.getRemoteFields();
return TextMapPropagator.composite(W3CTraceContextPropagator.getInstance(),
W3CBaggagePropagator.getInstance(), new BaggageTextMapPropagator(remoteFields,
return io.opentelemetry.context.propagation.TextMapPropagator.composite(io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator.getInstance(),
io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator.getInstance(), new BaggageTextMapPropagator(remoteFields,
new OtelBaggageManager(currentTraceContext, remoteFields, Collections.emptyList())));
}
return TextMapPropagator.noop();
return io.opentelemetry.context.propagation.TextMapPropagator.noop();
}
}
}

View File

@ -0,0 +1,23 @@
/*
* 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.tracing.utils;
public class ObservationConstants {
public static final String DEFAULT_APPLICATION_NAME = "dubbo-application";
}

Some files were not shown because too many files have changed in this diff Show More