├── .asf.yaml ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── example.rules ├── pom.xml ├── rocketmq_exporter.json ├── rocketmq_exporter_overview.json ├── rocketmq_exporter_quickstart.md ├── src ├── main │ ├── docker │ │ └── Dockerfile │ ├── java │ │ └── org │ │ │ └── apache │ │ │ └── rocketmq │ │ │ └── exporter │ │ │ ├── RocketMQExporterApplication.java │ │ │ ├── collector │ │ │ └── RMQMetricsCollector.java │ │ │ ├── config │ │ │ ├── CollectClientMetricExecutorConfig.java │ │ │ ├── RMQConfigure.java │ │ │ └── ScheduleConfig.java │ │ │ ├── controller │ │ │ └── RMQMetricsController.java │ │ │ ├── model │ │ │ ├── BrokerRuntimeStats.java │ │ │ ├── common │ │ │ │ └── TwoTuple.java │ │ │ └── metrics │ │ │ │ ├── BrokerMetric.java │ │ │ │ ├── ConsumerCountMetric.java │ │ │ │ ├── ConsumerMetric.java │ │ │ │ ├── ConsumerTopicDiffMetric.java │ │ │ │ ├── DLQTopicOffsetMetric.java │ │ │ │ ├── TopicPutNumMetric.java │ │ │ │ ├── brokerruntime │ │ │ │ └── BrokerRuntimeMetric.java │ │ │ │ ├── clientrunime │ │ │ │ ├── ConsumerRuntimeConsumeFailedMsgsMetric.java │ │ │ │ ├── ConsumerRuntimeConsumeFailedTPSMetric.java │ │ │ │ ├── ConsumerRuntimeConsumeOKTPSMetric.java │ │ │ │ ├── ConsumerRuntimeConsumeRTMetric.java │ │ │ │ ├── ConsumerRuntimePullRTMetric.java │ │ │ │ └── ConsumerRuntimePullTPSMetric.java │ │ │ │ └── producer │ │ │ │ ├── ProducerCountMetric.java │ │ │ │ └── ProducerMetric.java │ │ │ ├── otlp │ │ │ ├── OtlpGrpcLauncher.java │ │ │ └── OtlpMetricsCollectorService.java │ │ │ ├── service │ │ │ ├── RMQMetricsService.java │ │ │ ├── client │ │ │ │ ├── MQAdminExtImpl.java │ │ │ │ └── MQAdminInstance.java │ │ │ └── impl │ │ │ │ └── RMQMetricsServiceImpl.java │ │ │ ├── task │ │ │ ├── ClientMetricCollectorFixedThreadPoolExecutor.java │ │ │ ├── ClientMetricTaskRunnable.java │ │ │ └── MetricsCollectTask.java │ │ │ └── util │ │ │ ├── JsonUtil.java │ │ │ └── Utils.java │ └── resources │ │ ├── application.yml │ │ └── logback.xml └── test │ └── java │ └── org │ └── apache │ └── rocketmq │ └── exporter │ └── util │ └── UtilsTest.java └── style ├── copyright ├── Apache.xml └── profiles_settings.xml ├── rmq_checkstyle.xml └── rmq_codeStyle.xml /.asf.yaml: -------------------------------------------------------------------------------- 1 | notifications: 2 | commits: commits@rocketmq.apache.org 3 | issues: commits@rocketmq.apache.org 4 | pullrequests: commits@rocketmq.apache.org 5 | jobs: commits@rocketmq.apache.org 6 | discussions: dev@rocketmq.apache.org 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## What is the purpose of the change 2 | 3 | XXXXX 4 | 5 | ## Brief changelog 6 | 7 | XX 8 | 9 | ## Verifying this change 10 | 11 | XXXX 12 | 13 | Follow this checklist to help us incorporate your contribution quickly and easily. Notice, `it would be helpful if you could finish the following 5 checklist(the last one is not necessary)before request the community to review your PR`. 14 | 15 | - [x] Make sure there is a [Github issue](https://github.com/apache/rocketmq/issues) filed 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. 16 | - [x] Format the pull request title like `[ISSUE #123] Fix UnknownException when host config not exist`. Each commit in the pull request should have a meaningful subject line and body. 17 | - [x] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. 18 | - [x] Write necessary unit-test(over 80% coverage) 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 integration-test in [test module](https://github.com/apache/rocketmq/tree/master/test). 19 | - [x] Run `mvn -B clean apache-rat:check findbugs:findbugs checkstyle:checkstyle` to make sure basic checks pass. Run `mvn clean install -DskipITs` to make sure unit-test pass. Run `mvn clean test-compile failsafe:integration-test` to make sure integration-test pass. 20 | - [ ] If this contribution is large, please file an [Apache Individual Contributor License Agreement](http://www.apache.org/licenses/#clas). 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .classpath 3 | .project 4 | .settings/ 5 | target/ 6 | *.log* 7 | *.iml 8 | .idea/ 9 | *.versionsBackup 10 | !NOTICE-BIN 11 | !LICENSE-BIN 12 | .DS_Store 13 | .vscode 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | 3 | language: java 4 | 5 | matrix: 6 | include: 7 | # On OSX, run with default JDK only. 8 | # - os: osx 9 | # On Linux, run with specific JDKs only. 10 | - os: linux 11 | env: CUSTOM_JDK="oraclejdk8" 12 | 13 | before_install: 14 | - echo 'MAVEN_OPTS="$MAVEN_OPTS -Xmx1024m -XX:MaxPermSize=512m -XX:+BytecodeVerificationLocal"' >> ~/.mavenrc 15 | - cat ~/.mavenrc 16 | - if [ "$TRAVIS_OS_NAME" == "osx" ]; then export JAVA_HOME=$(/usr/libexec/java_home); fi 17 | - if [ "$TRAVIS_OS_NAME" == "linux" ]; then jdk_switcher use "$CUSTOM_JDK"; fi 18 | 19 | script: 20 | - travis_retry mvn -B clean apache-rat:check 21 | - travis_retry mvn -B clean install 22 | after_success: 23 | - bash <(curl -s https://codecov.io/bash) || echo 'Codecov failed to upload' 24 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## How To Contribute 2 | 3 | We are always very happy to have contributions, whether for trivial cleanups or big new features. 4 | We want to have high quality, well documented codes for each programming language, as well as the surrounding [ecosystem](https://github.com/apache/rocketmq-externals) of integration tools that people use with RocketMQ. 5 | 6 | Nor is code the only way to contribute to the project. We strongly value documentation, integration with other project, and gladly accept improvements for these aspects. 7 | 8 | ## Contributing code 9 | 10 | To submit a change for inclusion, please do the following: 11 | 12 | #### If the change is non-trivial please include some unit tests that cover the new functionality. 13 | #### If you are introducing a completely new feature or API it is a good idea to start a [RIP](https://github.com/apache/rocketmq/wiki/RocketMQ-Improvement-Proposal) and get consensus on the basic design first. 14 | #### It is our job to follow up on patches in a timely fashion. Nag us if we aren't doing our job (sometimes we drop things). 15 | 16 | ## Becoming a Committer 17 | 18 | We are always interested in adding new contributors. What we look for are series of contributions, good taste and ongoing interest in the project. If you are interested in becoming a committer, please let one of the existing committers know and they can help you walk through the process. 19 | 20 | Nowadays,we have several important contribution points: 21 | #### Wiki & JavaDoc 22 | #### RocketMQ SDK(C++\.Net\Php\Python\Go\Node.js) 23 | #### RocketMQ Connectors 24 | 25 | ##### Prerequisite 26 | If you want to contribute the above listing points, you must abide our some prerequisites: 27 | 28 | ###### Readability - API must have Javadoc,some very important methods also must have javadoc 29 | ###### Testability - 80% above unit test coverage about main process 30 | ###### Maintainability - Comply with our [checkstyle spec](style/rmq_checkstyle.xml), and at least 3 month update frequency 31 | ###### Deployability - We encourage you to deploy into [maven repository](http://search.maven.org/) 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Apache RocketMQ 2 | Copyright 2016-2021 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apache RocketMQ Exporter for Prometheus. 2 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) 3 | [![Build Status](https://api.travis-ci.com/apache/rocketmq-exporter.svg?branch=master)](https://travis-ci.com/github/apache/rocketmq-exporter) 4 | [![codecov](https://codecov.io/gh/apache/rocketmq-exporter/branch/master/graph/badge.svg?token=jS7OXwJW5Q)](https://codecov.io/gh/apache/rocketmq-exporter) 5 | [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/apache/rocketmq-exporter.svg)](http://isitmaintained.com/project/apache/rocketmq-exporter "Average time to resolve an issue") 6 | [![Percentage of issues still open](http://isitmaintained.com/badge/open/apache/rocketmq-exporter.svg)](http://isitmaintained.com/project/apache/rocketmq-exporter "Percentage of issues still open") 7 | ![Twitter Follow](https://img.shields.io/twitter/follow/ApacheRocketMQ?style=social) 8 | 9 | 10 | Table of Contents 11 | ----------------- 12 | - [Compatibility](#compatibility) 13 | - [Configuration](#configuration) 14 | - [Build](#build) 15 | - [Build Binary](#build-binary) 16 | - [Build Docker Image](#build-docker-image) 17 | - [Run](#run) 18 | - [Run Binary](#run-binary) 19 | - [Run Docker Image](#run-docker-image) 20 | - [Metrics](#metrics) 21 | - [Broker](#broker) 22 | - [Producer](#producer) 23 | - [Consumer Groups](#consumer-groups) 24 | - [Consumer](#consumer) 25 | - [Grafana Dashboard](#grafana-dashboard) 26 | - [SkyWalking Dashboard](#skywalking-dashboard) 27 | - [Quick Start](#quick-start) 28 | 29 | Compatibility 30 | ------------- 31 | 32 | Support [Apache RocketMQ](https://rocketmq.apache.org) version 4.3.2 (and later). 33 | 34 | 35 | Configuration 36 | --- 37 | 38 | This image is configurable using different properties, see ``application.properties`` for a configuration example. 39 | 40 | | name | Default | Description | 41 | | -----------------------------------|--------------------|----------------------------------------------------| 42 | | `rocketmq.config.namesrvAddr` | 127.0.0.1:9876 |name server address for broker cluster | 43 | | `rocketmq.config.webTelemetryPath` | /metrics |Path under which to expose metrics | 44 | | `server.port` | 5557 |Address to listen on for web interface and telemetry| 45 | | `rocketmq.config.rocketmqVersion` | V4_3_2 |rocketmq broker version | 46 | 47 | 48 | Build 49 | ------- 50 | 51 | ### Build Binary 52 | 53 | ```shell 54 | mvn clean install 55 | ``` 56 | 57 | ### Build Docker Image 58 | 59 | ```shell 60 | mvn package -Dmaven.test.skip=true docker:build 61 | ``` 62 | 63 | Run 64 | --- 65 | 66 | ### Run Binary 67 | 68 | ```shell 69 | java -jar target/rocketmq-exporter-0.0.2-SNAPSHOT-exec.jar 70 | ``` 71 | 72 | ### Run Docker Image 73 | 74 | ``` 75 | docker container run -itd --rm -p 5557:5557 docker.io/rocketmq-exporter 76 | ``` 77 | 78 | 79 | Metrics 80 | ------- 81 | 82 | Documents about exposed Prometheus metrics. 83 | 84 | ### Broker 85 | 86 | **Metrics details** 87 | 88 | | Name | Exposed information | 89 | | ------------ | ---------------------------------------------------- | 90 | | `rocketmq_broker_tps` | Broker produces the number of messages per second | 91 | | `rocketmq_broker_qps` | Broker consumes messages per second | 92 | 93 | **Metrics output example** 94 | 95 | ```txt 96 | # HELP rocketmq_broker_tps BrokerPutNums 97 | # TYPE rocketmq_broker_tps gauge 98 | rocketmq_broker_tps{cluster="MQCluster",broker="broker-a",} 7.0 99 | rocketmq_broker_tps{cluster="MQCluster",broker="broker-b",} 7.0 100 | # HELP rocketmq_broker_qps BrokerGetNums 101 | # TYPE rocketmq_broker_qps gauge 102 | rocketmq_broker_qps{cluster="MQCluster",broker="broker-a",} 8.0 103 | rocketmq_broker_qps{cluster="MQCluster",broker="broker-b",} 8.0 104 | ``` 105 | 106 | ### Producer 107 | 108 | **Metrics details** 109 | 110 | | Name | Exposed information | 111 | | ------------------- | -------------------------------------------------- | 112 | | `rocketmq_producer_tps` | The number of messages produced per second per topic | 113 | | `rocketmq_producer_message_size` | The size of a message produced per second by a topic (in bytes) | 114 | | `rocketmq_producer_offset` | The progress of a topic's production message | 115 | 116 | **Metrics output example** 117 | 118 | ```txt 119 | # HELP rocketmq_producer_tps TopicPutNums 120 | # TYPE rocketmq_producer_tps gauge 121 | rocketmq_producer_tps{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",} 7.0 122 | rocketmq_producer_tps{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",} 7.0 123 | # HELP rocketmq_producer_message_size TopicPutMessageSize 124 | # TYPE rocketmq_producer_message_size gauge 125 | rocketmq_producer_message_size{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",} 1642.0 126 | rocketmq_producer_message_size{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",} 1638.0 127 | # HELP rocketmq_producer_offset TopicOffset 128 | # TYPE rocketmq_producer_offset counter 129 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="TBW102",} 0.0 130 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="DEV_TID_tfq",} 1878633.0 131 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="DEV_TID_tfq",} 3843787.0 132 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="DEV_TID_20190304",} 0.0 133 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="BenchmarkTest",} 0.0 134 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="DEV_TID_20190305",} 0.0 135 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="MQCluster",} 0.0 136 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",} 2798195.0 137 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="BenchmarkTest",} 0.0 138 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",} 1459666.0 139 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="MQCluster",} 0.0 140 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="SELF_TEST_TOPIC",} 0.0 141 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="OFFSET_MOVED_EVENT",} 0.0 142 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="broker-b",} 0.0 143 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="broker-a",} 0.0 144 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="SELF_TEST_TOPIC",} 0.0 145 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="RMQ_SYS_TRANS_HALF_TOPIC",} 0.0 146 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="DEV_TID_20190305",} 0.0 147 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="OFFSET_MOVED_EVENT",} 0.0 148 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="RMQ_SYS_TRANS_HALF_TOPIC",} 0.0 149 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-b",topic="TBW102",} 0.0 150 | rocketmq_producer_offset{cluster="MQCluster",broker="broker-a",topic="DEV_TID_20190304",} 0.0 151 | 152 | ``` 153 | 154 | ### Consumer Groups 155 | 156 | **Metrics details** 157 | 158 | | Name | Exposed information | 159 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 160 | | `rocketmq_consumer_tps` | The number of messages consumed per second by a consumer group | 161 | | `rocketmq_consumer_message_size` | The size of the message consumed by the consumer group per second (in bytes) | 162 | | `rocketmq_consumer_offset` | Progress of consumption message for a consumer group | 163 | | `rocketmq_group_get_latency` | Consumer latency on some topic for one queue | 164 | | `rocketmq_group_get_latency_by_storetime ` | Consumption delay time of a consumer group | 165 | | `rocketmq_message_accumulation`| How far Consumer offset lag behind | 166 | 167 | **Metrics output example** 168 | 169 | ```txt 170 | # HELP rocketmq_consumer_tps GroupGetNums 171 | # TYPE rocketmq_consumer_tps gauge 172 | rocketmq_consumer_tps{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",} 7.0 173 | rocketmq_consumer_tps{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",} 7.0 174 | # HELP rocketmq_consumer_message_size GroupGetMessageSize 175 | # TYPE rocketmq_consumer_message_size gauge 176 | rocketmq_consumer_message_size{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",} 1638.0 177 | rocketmq_consumer_message_size{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",} 1642.0 178 | # HELP rocketmq_consumer_offset GroupOffset 179 | # TYPE rocketmq_consumer_offset counter 180 | rocketmq_consumer_offset{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",} 1462030.0 181 | rocketmq_consumer_offset{cluster="MQCluster",broker="broker-a",topic="DEV_TID_tfq",group="DEV_CID_cfq",} 3843787.0 182 | rocketmq_consumer_offset{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",} 2800569.0 183 | rocketmq_consumer_offset{cluster="MQCluster",broker="broker-b",topic="DEV_TID_tfq",group="DEV_CID_cfq",} 1878633.0 184 | # HELP rocketmq_group_get_latency GroupGetLatency 185 | # TYPE rocketmq_group_get_latency gauge 186 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="0",} 0.05 187 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="1",} 0.0 188 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="7",} 0.05 189 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="6",} 0.01 190 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="3",} 0.0 191 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="7",} 0.03 192 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="4",} 0.0 193 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="5",} 0.03 194 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="6",} 0.01 195 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="2",} 0.0 196 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="3",} 0.0 197 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="0",} 0.0 198 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="4",} 0.0 199 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="1",} 0.03 200 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="5",} 0.0 201 | rocketmq_group_get_latency{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",queueid="2",} 0.0 202 | # HELP rocketmq_group_get_latency_by_storetime GroupGetLatencyByStoreTime 203 | # TYPE rocketmq_group_get_latency_by_storetime gauge 204 | rocketmq_group_get_latency_by_storetime{cluster="MQCluster",broker="broker-b",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",} 3215.0 205 | rocketmq_group_get_latency_by_storetime{cluster="MQCluster",broker="broker-a",topic="DEV_TID_tfq",group="DEV_CID_cfq",} 0.0 206 | rocketmq_group_get_latency_by_storetime{cluster="MQCluster",broker="broker-a",topic="DEV_TID_topic_tfq",group="DEV_CID_consumer_cfq",} 3232.0 207 | rocketmq_group_get_latency_by_storetime{cluster="MQCluster",broker="broker-b",topic="DEV_TID_tfq",group="DEV_CID_cfq",} 0.0 208 | ``` 209 | 210 | ### Consumer 211 | 212 | **Metrics details** 213 | 214 | | Name | Exposed information | 215 | | ---------------------------------------- | -------------------------------------------------- | 216 | | `rocketmq_client_consume_fail_msg_count` | The number of messages consumed fail in one hour | 217 | | `rocketmq_client_consume_fail_msg_tps` | The number of messages consumed fail per second | 218 | | `rocketmq_client_consume_ok_msg_tps` | The number of messages consumed success per second | 219 | | `rocketmq_client_consume_rt` | The average time of consuming every message | 220 | | `rocketmq_client_consumer_pull_rt ` | The average time of pulling every message | 221 | | `rocketmq_client_consumer_pull_tps` | The number of messages pulled by client per second | 222 | 223 | **Metrics output example** 224 | 225 | ``` 226 | # HELP rocketmq_client_consume_fail_msg_count consumerClientFailedMsgCounts 227 | # TYPE rocketmq_client_consume_fail_msg_count gauge 228 | rocketmq_client_consume_fail_msg_count{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="topic_one",} 0.0 229 | rocketmq_client_consume_fail_msg_count{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="%RETRY%consumer_one",} 0.0 230 | # HELP rocketmq_client_consume_fail_msg_tps consumerClientFailedTPS 231 | # TYPE rocketmq_client_consume_fail_msg_tps gauge 232 | rocketmq_client_consume_fail_msg_tps{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="topic_one",} 0.0 233 | rocketmq_client_consume_fail_msg_tps{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="%RETRY%consumer_one",} 0.0 234 | # HELP rocketmq_client_consume_ok_msg_tps consumerClientOKTPS 235 | # TYPE rocketmq_client_consume_ok_msg_tps gauge 236 | rocketmq_client_consume_ok_msg_tps{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="topic_one",} 9.833333333333334 237 | rocketmq_client_consume_ok_msg_tps{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="%RETRY%consumer_one",} 0.0 238 | # HELP rocketmq_client_consume_rt consumerClientRT 239 | # TYPE rocketmq_client_consume_rt gauge 240 | rocketmq_client_consume_rt{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="topic_one",} 0.0576271186440678 241 | rocketmq_client_consume_rt{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="%RETRY%consumer_one",} 0.0 242 | # HELP rocketmq_client_consumer_pull_rt consumerClientPullRT 243 | # TYPE rocketmq_client_consumer_pull_rt gauge 244 | rocketmq_client_consumer_pull_rt{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="topic_one",} 402.6186440677966 245 | rocketmq_client_consumer_pull_rt{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="%RETRY%consumer_one",} 0.0 246 | # HELP rocketmq_client_consumer_pull_tps consumerClientPullTPS 247 | # TYPE rocketmq_client_consumer_pull_tps gauge 248 | rocketmq_client_consumer_pull_tps{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="topic_one",} 9.833333333333334 249 | rocketmq_client_consumer_pull_tps{clientAddr="172.16.116.51:52178",clientId="10.0.4.0@120367",group="consumer_one",topic="%RETRY%consumer_one",} 0.0 250 | ``` 251 | 252 | Grafana Dashboard 253 | ------- 254 | There are two dashboard to choose from: 255 | ### The First 256 | Grafana Dashboard ID: 10477, name: RocketMQ Exporter Overview. 257 | For details of the dashboard please see [RocketMQ Exporter Overview](https://grafana.com/grafana/dashboards/10477-rocketmq-dashboard/). 258 | 259 | SkyWalking Dashboard 260 | ------- 261 | 262 | Since 10.0, SkyWalking has provided bundled native monitoring dashboards for RocketMQ through this exporter and OpenTelemetry collector. 263 | For settings details, please read [RocketMQ monitoring doc](https://skywalking.apache.org/docs/main/next/en/setup/backend/backend-rocketmq-monitoring/). 264 | 265 | ### The Second 266 | [rocketmq_exporter.json](./rocketmq_exporter.json) 267 | 268 | **Note**: It must be configured with two additional labels(Env and Cluster), when configured on the prometheus, as shown bellow: 269 | ```yaml 270 | - job_name: 'rocketmq-exporter' 271 | static_configs: 272 | - targets: ['localhost:5557'] 273 | labels: 274 | Env: 'develop' 275 | Cluster: 'local' 276 | ``` 277 | Quick Start 278 | ------------- 279 | This [guide](./rocketmq_exporter_quickstart.md) will tell you how to build and run rocketmq exporter with Prometheus and Grafana Integration from scratch. 280 | -------------------------------------------------------------------------------- /example.rules: -------------------------------------------------------------------------------- 1 | ### 2 | # Sample prometheus rules/alerts for rocketmq. 3 | # 4 | # NOTE: Please review these carefully as thresholds and behavior may not meet 5 | # your SLOs or labels. 6 | # 7 | 8 | ### 9 | # Recording Rules 10 | 11 | 12 | ### 13 | # Galera Alerts 14 | 15 | groups: 16 | - name: GaleraAlerts 17 | rules: 18 | - alert: RocketMQClusterProduceHigh 19 | expr: sum(rocketmq_producer_tps) by (cluster) >= 10 20 | for: 3m 21 | labels: 22 | severity: warning 23 | annotations: 24 | description: '{{$labels.cluster}} Sending tps too high.' 25 | summary: cluster send tps too high 26 | - alert: RocketMQClusterProduceLow 27 | expr: sum(rocketmq_producer_tps) by (cluster) < 1 28 | for: 3m 29 | labels: 30 | severity: warning 31 | annotations: 32 | description: '{{$labels.cluster}} Sending tps too low.' 33 | summary: cluster send tps too low 34 | - alert: RocketMQClusterConsumeHigh 35 | expr: sum(rocketmq_consumer_tps) by (cluster) >= 10 36 | for: 3m 37 | labels: 38 | severity: warning 39 | annotations: 40 | description: '{{$labels.cluster}} consuming tps too high.' 41 | summary: cluster consume tps too high 42 | - alert: RocketMQClusterConsumeLow 43 | expr: sum(rocketmq_consumer_tps) by (cluster) < 1 44 | for: 3m 45 | labels: 46 | severity: warning 47 | annotations: 48 | description: '{{$labels.cluster}} consuming tps too low.' 49 | summary: cluster consume tps too low 50 | - alert: ConsumerFallingBehind 51 | expr: (sum(rocketmq_producer_offset) by (topic) - on(topic) group_right sum(rocketmq_consumer_offset) by (group,topic)) - ignoring(group) group_left sum (avg_over_time(rocketmq_producer_tps[5m])) by (topic)*5*60 > 0 52 | for: 3m 53 | labels: 54 | severity: warning 55 | annotations: 56 | description: 'consumer {{$labels.group}} on {{$labels.topic}} lag behind 57 | and is falling behind (behind value {{$value}}).' 58 | summary: consumer lag behind 59 | - alert: GroupGetLatencyByStoretime 60 | expr: rocketmq_group_get_latency_by_storetime > 1000 61 | for: 3m 62 | labels: 63 | severity: warning 64 | annotations: 65 | description: 'consumer {{$labels.group}} on {{$labels.broker}}, {{$labels.topic}} consume time lag behind message store time 66 | and (behind value is {{$value}}).' 67 | summary: message consumes time lag behind message store time too much 68 | -------------------------------------------------------------------------------- /rocketmq_exporter_quickstart.md: -------------------------------------------------------------------------------- 1 | # Quick Start # 2 | 3 | ## Start up NameServer and Broker 4 | To use RocketMQ Exporter, first make sure the RocketMQ is downloaded and started correctly. Users can refer to [quick start](http://rocketmq.apache.org/docs/quick-start/) ensure that the service starts properly. 5 | 6 | ## Build and Run RocketMQ Exporter 7 | 8 | 9 | ## Install Prometheus 10 | Download [Prometheus installation package](https://prometheus.io/download/) and install it. 11 | 12 | ``` 13 | tar -xzf prometheus-2.7.0-rc.1.linux-amd64.tar.gz 14 | cd prometheus-2.7.0-rc.1.linux-amd64/ 15 | ./prometheus --config.file=prometheus.yml --web.listen-address=:5555 16 | ``` 17 | 18 | The content of prometheus.yml is as follows. 19 | 20 | ``` 21 | # Global config 22 | global: 23 | scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. 24 | evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. 25 | # scrape_timeout is set to the global default (10s). 26 | 27 | 28 | # Load rules once and periodically evaluate them according to the global 'evaluation_interval'. 29 | rule_files: 30 | # - "first_rules.yml" 31 | # - "second_rules.yml" 32 | 33 | 34 | scrape_configs: 35 | - job_name: 'prometheus' 36 | static_configs: 37 | - targets: ['localhost:5555'] 38 | 39 | 40 | - job_name: 'exporter' 41 | static_configs: 42 | - targets: ['localhost:5557'] 43 | ``` 44 | 45 | 46 | 47 | ## Integration with Grafana Dashboard 48 | 49 | Download Grafana installation package and install it. 50 | 51 | 52 | ``` 53 | wget https://dl.grafana.com/oss/release/grafana-6.2.5.linux-amd64.tar.gz 54 | tar -zxvf grafana-6.2.5.linux-amd64.tar.gz 55 | cd grafana-5.4.3/ 56 | ``` 57 | The user can modify the listener port in the default.ini file in the conf directory. Currently, the Grafana listener port changes to 55555 and starts with the following command. 58 | 59 | ``` 60 | ./bin/grafana-server web 61 | ``` 62 | 63 | The user can verify that Grafana has been successfully installed by visiting http:// server IP :55555 in a browser. The default system username and password is admin/admin. The first time the user logs into the system, the system will ask the user to change the password. In addition, the user needs to set the data source of Grafana as Prometheus. If Prometheus was launched by the user as above, the data source address will now be http:// server IP :5555. For the convenience of users, RocketMQ dashboard configuration file has been uploaded to the Grafana's official website https://grafana.com/dashboards/10477/revisions. The user simply downloads the configuration file and imports the Grafana. 64 | 65 | ## Configure alarms in Prometheus 66 | 67 | The user wants to configure monitoring alerts, there are two things the user should do. 68 | First, modify the Prometheus configuration file. And add the following configuration. 69 | 70 | ``` 71 | rule_files: 72 | - /etc/prometheus/rules/*.rules 73 | ``` 74 | 75 | Secondly, create an alert file in the directory /etc/prometheus/rules/. The content of rules file will be like as follows. For more details, please refer to the file [example.rules](./example.rules) 76 | 77 | ``` 78 | groups: 79 | - name: GaleraAlerts 80 | rules: 81 | - alert: RocketMQClusterProduceHigh 82 | expr: sum(rocketmq_producer_tps) by (cluster) >= 10 83 | for: 3m 84 | labels: 85 | severity: warning 86 | annotations: 87 | description: '{{$labels.cluster}} Sending tps too high.' 88 | summary: cluster send tps too high 89 | - alert: RocketMQClusterProduceLow 90 | expr: sum(rocketmq_producer_tps) by (cluster) < 1 91 | for: 3m 92 | labels: 93 | severity: warning 94 | annotations: 95 | description: '{{$labels.cluster}} Sending tps too low.' 96 | summary: cluster send tps too low 97 | ``` 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one or more 3 | # contributor license agreements. See the NOTICE file distributed with 4 | # this work for additional information regarding copyright ownership. 5 | # The ASF licenses this file to You under the Apache License, Version 2.0 6 | # (the "License"); you may not use this file except in compliance with 7 | # the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | FROM java:8 19 | MAINTAINER breeze 20 | ADD rocketmq-exporter-0.0.2-SNAPSHOT-exec.jar rocketmq-exporter.jar 21 | EXPOSE 5557 22 | ENTRYPOINT ["java","-jar","rocketmq-exporter.jar"] 23 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/RocketMQExporterApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter; 18 | 19 | import org.springframework.boot.CommandLineRunner; 20 | import org.springframework.boot.SpringApplication; 21 | import org.springframework.boot.autoconfigure.SpringBootApplication; 22 | import org.springframework.boot.web.servlet.ServletComponentScan; 23 | import org.springframework.scheduling.annotation.EnableScheduling; 24 | 25 | @SpringBootApplication 26 | @ServletComponentScan 27 | @EnableScheduling 28 | public class RocketMQExporterApplication implements CommandLineRunner { 29 | 30 | 31 | public static void main(String[] args) { 32 | SpringApplication.run(RocketMQExporterApplication.class, args); 33 | } 34 | 35 | @Override 36 | public void run(String... args) throws Exception { 37 | return; 38 | } 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/config/CollectClientMetricExecutorConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.config; 18 | 19 | 20 | import org.springframework.boot.context.properties.ConfigurationProperties; 21 | import org.springframework.context.annotation.Configuration; 22 | 23 | @Configuration 24 | @ConfigurationProperties(prefix = "threadpool.collect-client-metric-executor") 25 | public class CollectClientMetricExecutorConfig { 26 | private int corePoolSize = 20; 27 | private int maximumPoolSize = 20; 28 | private long keepAliveTime = 4000L; 29 | private int queueSize = 1000; 30 | 31 | public int getCorePoolSize() { 32 | return corePoolSize; 33 | } 34 | 35 | public void setCorePoolSize(int corePoolSize) { 36 | this.corePoolSize = corePoolSize; 37 | } 38 | 39 | public int getMaximumPoolSize() { 40 | return maximumPoolSize; 41 | } 42 | 43 | public void setMaximumPoolSize(int maximumPoolSize) { 44 | this.maximumPoolSize = maximumPoolSize; 45 | } 46 | 47 | public long getKeepAliveTime() { 48 | return keepAliveTime; 49 | } 50 | 51 | public void setKeepAliveTime(long keepAliveTime) { 52 | this.keepAliveTime = keepAliveTime; 53 | } 54 | 55 | public int getQueueSize() { 56 | return queueSize; 57 | } 58 | 59 | public void setQueueSize(int queueSize) { 60 | this.queueSize = queueSize; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/config/RMQConfigure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.config; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | import org.apache.rocketmq.common.MixAll; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.springframework.boot.context.properties.ConfigurationProperties; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | import static org.apache.rocketmq.client.ClientConfig.SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY; 27 | 28 | @Configuration 29 | @ConfigurationProperties(prefix = "rocketmq.config") 30 | public class RMQConfigure { 31 | 32 | public static final String ROCKETMQ_CONFIG_WEB_TELEMETRY_PATH = "rocketmq.config.webTelemetryPath"; 33 | public static final String ROCKETMQ_CONFIG_ROCKETMQ_VERSION = "rocketmq.config.rocketmqVersion"; 34 | 35 | private Logger logger = LoggerFactory.getLogger(RMQConfigure.class); 36 | //use rocketmq.namesrv.addr first,if it is empty,than use system property or system env 37 | private volatile String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY, System.getenv(MixAll.NAMESRV_ADDR_ENV)); 38 | 39 | private volatile String isVIPChannel = System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, "true"); 40 | 41 | private boolean enableCollect; 42 | 43 | private volatile String webTelemetryPath = System.getProperty(ROCKETMQ_CONFIG_WEB_TELEMETRY_PATH, "/metrics"); 44 | 45 | private volatile String rocketmqVersion = System.getProperty(ROCKETMQ_CONFIG_ROCKETMQ_VERSION, "V4_3_2"); 46 | 47 | /** 48 | * true: accessKey and secretKey would be used 49 | * default false 50 | */ 51 | private boolean enableACL = false; 52 | 53 | private String accessKey; 54 | 55 | private String secretKey; 56 | 57 | private long outOfTimeSeconds; 58 | 59 | public boolean enableACL() { 60 | return this.enableACL; 61 | } 62 | 63 | public void setEnableACL(boolean enableACL) { 64 | this.enableACL = enableACL; 65 | } 66 | 67 | public String getNamesrvAddr() { 68 | return namesrvAddr; 69 | } 70 | 71 | public void setNamesrvAddr(String namesrvAddr) { 72 | if (StringUtils.isNotBlank(namesrvAddr)) { 73 | this.namesrvAddr = namesrvAddr; 74 | System.setProperty(MixAll.NAMESRV_ADDR_PROPERTY, namesrvAddr); 75 | logger.info("setNameSrvAddrByProperty nameSrvAddr={}", namesrvAddr); 76 | } 77 | } 78 | 79 | public String getIsVIPChannel() { 80 | return isVIPChannel; 81 | } 82 | 83 | public void setIsVIPChannel(String isVIPChannel) { 84 | if (StringUtils.isNotBlank(isVIPChannel)) { 85 | this.isVIPChannel = isVIPChannel; 86 | System.setProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, isVIPChannel); 87 | logger.info("setIsVIPChannel isVIPChannel={}", isVIPChannel); 88 | } 89 | } 90 | 91 | public boolean isEnableCollect() { 92 | return enableCollect; 93 | } 94 | 95 | public void setEnableCollect(boolean enableCollect) { 96 | this.enableCollect = enableCollect; 97 | } 98 | 99 | public void setWebTelemetryPath(String webTelemetryPath) { 100 | if (StringUtils.isNotBlank(webTelemetryPath)) { 101 | this.webTelemetryPath = webTelemetryPath; 102 | System.setProperty(ROCKETMQ_CONFIG_WEB_TELEMETRY_PATH, webTelemetryPath); 103 | logger.info("setWebTelemetryPath webTelemetryPath={}", webTelemetryPath); 104 | } 105 | } 106 | 107 | public String getWebTelemetryPath() { 108 | return webTelemetryPath; 109 | } 110 | 111 | public void setRocketmqVersion(String rocketmqVersion) { 112 | if (StringUtils.isNotBlank(rocketmqVersion)) { 113 | this.rocketmqVersion = rocketmqVersion; 114 | System.setProperty(ROCKETMQ_CONFIG_ROCKETMQ_VERSION, rocketmqVersion); 115 | logger.info("setRocketmqVersion rocketmqVersion={}", rocketmqVersion); 116 | } 117 | } 118 | 119 | public String getRocketmqVersion() { 120 | return rocketmqVersion; 121 | } 122 | 123 | public String getAccessKey() { 124 | return accessKey; 125 | } 126 | 127 | public void setAccessKey(String accessKey) { 128 | this.accessKey = accessKey; 129 | } 130 | 131 | public String getSecretKey() { 132 | return secretKey; 133 | } 134 | 135 | public void setSecretKey(String secretKey) { 136 | this.secretKey = secretKey; 137 | } 138 | 139 | public long getOutOfTimeSeconds() { 140 | return outOfTimeSeconds; 141 | } 142 | 143 | public void setOutOfTimeSeconds(long outOfTimeSeconds) { 144 | this.outOfTimeSeconds = outOfTimeSeconds; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/config/ScheduleConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.config; 18 | 19 | import org.springframework.beans.factory.annotation.Value; 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.scheduling.annotation.SchedulingConfigurer; 23 | import org.springframework.scheduling.config.ScheduledTaskRegistrar; 24 | 25 | import java.util.concurrent.Executor; 26 | import java.util.concurrent.Executors; 27 | 28 | @Configuration 29 | public class ScheduleConfig implements SchedulingConfigurer { 30 | @Override 31 | public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { 32 | taskRegistrar.setScheduler(taskExecutor()); 33 | } 34 | 35 | @Value("${task.count}") 36 | private int taskCount; 37 | 38 | @Bean(destroyMethod = "shutdown") 39 | public Executor taskExecutor() { 40 | return Executors.newScheduledThreadPool(this.taskCount); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/controller/RMQMetricsController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.controller; 18 | 19 | 20 | import org.apache.rocketmq.exporter.service.RMQMetricsService; 21 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 22 | import org.springframework.web.bind.annotation.RequestMapping; 23 | import org.springframework.web.bind.annotation.ResponseBody; 24 | import org.springframework.web.bind.annotation.RestController; 25 | 26 | import javax.annotation.Resource; 27 | import javax.servlet.http.HttpServletResponse; 28 | import java.io.IOException; 29 | import java.io.StringWriter; 30 | 31 | @RestController 32 | @EnableAutoConfiguration 33 | public class RMQMetricsController { 34 | @Resource 35 | RMQMetricsService metricsService; 36 | 37 | @RequestMapping(value = "${rocketmq.config.webTelemetryPath}") 38 | @ResponseBody 39 | private void metrics(HttpServletResponse response) throws IOException { 40 | StringWriter writer = new StringWriter(); 41 | metricsService.metrics(writer); 42 | response.setHeader("Content-Type", "text/plain; version=0.0.4; charset=utf-8"); 43 | response.getOutputStream().print(writer.toString()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/BrokerRuntimeStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model; 18 | 19 | import org.apache.rocketmq.common.protocol.body.KVTable; 20 | import org.apache.rocketmq.exporter.util.Utils; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import java.util.ArrayList; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | public class BrokerRuntimeStats { 30 | private long msgPutTotalTodayNow; 31 | private long msgGetTotalTodayNow; 32 | private long msgPutTotalTodayMorning; 33 | private long msgGetTotalTodayMorning; 34 | private long msgPutTotalYesterdayMorning; 35 | private long msgGetTotalYesterdayMorning; 36 | private List scheduleMessageOffsetTables = new ArrayList<>(); 37 | private long sendThreadPoolQueueHeadWaitTimeMills; 38 | private long queryThreadPoolQueueHeadWaitTimeMills; 39 | private long pullThreadPoolQueueHeadWaitTimeMills; 40 | private long queryThreadPoolQueueSize; 41 | private long pullThreadPoolQueueSize; 42 | private long sendThreadPoolQueueCapacity; 43 | private long pullThreadPoolQueueCapacity; 44 | private Map putMessageDistributeTimeMap = new HashMap<>(); 45 | private double remainHowManyDataToFlush; 46 | private long commitLogMinOffset; 47 | private long commitLogMaxOffset; 48 | private String runtime; 49 | private long bootTimestamp; 50 | private double commitLogDirCapacityTotal; 51 | private double commitLogDirCapacityFree; 52 | private int brokerVersion; 53 | private long dispatchMaxBuffer; 54 | 55 | private PutTps putTps = new PutTps(); 56 | private GetMissTps getMissTps = new GetMissTps(); 57 | private GetTransferedTps getTransferedTps = new GetTransferedTps(); 58 | private GetTotalTps getTotalTps = new GetTotalTps(); 59 | private GetFoundTps getFoundTps = new GetFoundTps(); 60 | 61 | private double consumeQueueDiskRatio; 62 | private double commitLogDiskRatio; 63 | 64 | private long pageCacheLockTimeMills; 65 | 66 | private long getMessageEntireTimeMax; 67 | 68 | private long putMessageTimesTotal; 69 | 70 | private String brokerVersionDesc; 71 | private long sendThreadPoolQueueSize; 72 | private long startAcceptSendRequestTimeStamp; 73 | private long putMessageEntireTimeMax; 74 | private long earliestMessageTimeStamp; 75 | 76 | private long remainTransientStoreBufferNumbs; 77 | private long queryThreadPoolQueueCapacity; 78 | private double putMessageAverageSize; 79 | private long putMessageSizeTotal; 80 | private long dispatchBehindBytes; 81 | private double putLatency99; 82 | private double putLatency999; 83 | 84 | 85 | private final static Logger log = LoggerFactory.getLogger(BrokerRuntimeStats.class); 86 | public BrokerRuntimeStats(KVTable kvTable) { 87 | this.msgPutTotalTodayNow = Long.parseLong(kvTable.getTable().get("msgPutTotalTodayNow")); 88 | 89 | loadScheduleMessageOffsets(kvTable); 90 | loadPutMessageDistributeTime(kvTable.getTable().get("putMessageDistributeTime")); 91 | 92 | loadTps(this.putTps, kvTable.getTable().get("putTps")); 93 | loadTps(this.getMissTps, kvTable.getTable().get("getMissTps")); 94 | if (kvTable.getTable().containsKey("getTransferredTps")) { 95 | loadTps(this.getTransferedTps, kvTable.getTable().get("getTransferredTps")); 96 | } else { 97 | loadTps(this.getTransferedTps, kvTable.getTable().get("getTransferedTps")); 98 | } 99 | loadTps(this.getTotalTps, kvTable.getTable().get("getTotalTps")); 100 | loadTps(this.getFoundTps, kvTable.getTable().get("getFoundTps")); 101 | 102 | loadCommitLogDirCapacity(kvTable.getTable().get("commitLogDirCapacity")); 103 | 104 | this.sendThreadPoolQueueHeadWaitTimeMills = Long.parseLong(kvTable.getTable().get("sendThreadPoolQueueHeadWaitTimeMills")); 105 | this.queryThreadPoolQueueHeadWaitTimeMills = Long.parseLong(kvTable.getTable().get("queryThreadPoolQueueHeadWaitTimeMills")); 106 | 107 | this.remainHowManyDataToFlush = Double.parseDouble(kvTable.getTable().get("remainHowManyDataToFlush").split(" ")[0]);//byte 108 | this.msgGetTotalTodayNow = Long.parseLong(kvTable.getTable().get("msgGetTotalTodayNow")); 109 | this.queryThreadPoolQueueSize = Long.parseLong(kvTable.getTable().get("queryThreadPoolQueueSize")); 110 | this.bootTimestamp = Long.parseLong(kvTable.getTable().get("bootTimestamp")); 111 | this.msgPutTotalYesterdayMorning = Long.parseLong(kvTable.getTable().get("msgPutTotalYesterdayMorning")); 112 | this.msgGetTotalYesterdayMorning = Long.parseLong(kvTable.getTable().get("msgGetTotalYesterdayMorning")); 113 | this.pullThreadPoolQueueSize = Long.parseLong(kvTable.getTable().get("pullThreadPoolQueueSize")); 114 | this.commitLogMinOffset = Long.parseLong(kvTable.getTable().get("commitLogMinOffset")); 115 | this.pullThreadPoolQueueHeadWaitTimeMills = Long.parseLong(kvTable.getTable().get("pullThreadPoolQueueHeadWaitTimeMills")); 116 | this.runtime = kvTable.getTable().get("runtime"); 117 | this.dispatchMaxBuffer = Long.parseLong(kvTable.getTable().get("dispatchMaxBuffer")); 118 | this.brokerVersion = Integer.parseInt(kvTable.getTable().get("brokerVersion")); 119 | this.consumeQueueDiskRatio = Double.parseDouble(kvTable.getTable().get("consumeQueueDiskRatio")); 120 | this.pageCacheLockTimeMills = Long.parseLong(kvTable.getTable().get("pageCacheLockTimeMills")); 121 | this.commitLogDiskRatio = Double.parseDouble(kvTable.getTable().get("commitLogDiskRatio")); 122 | this.commitLogMaxOffset = Long.parseLong(kvTable.getTable().get("commitLogMaxOffset")); 123 | this.getMessageEntireTimeMax = Long.parseLong(kvTable.getTable().get("getMessageEntireTimeMax")); 124 | this.msgPutTotalTodayMorning = Long.parseLong(kvTable.getTable().get("msgPutTotalTodayMorning")); 125 | this.putMessageTimesTotal = Long.parseLong(kvTable.getTable().get("putMessageTimesTotal")); 126 | this.msgGetTotalTodayMorning = Long.parseLong(kvTable.getTable().get("msgGetTotalTodayMorning")); 127 | this.brokerVersionDesc = kvTable.getTable().get("brokerVersionDesc"); 128 | this.sendThreadPoolQueueSize = Long.parseLong(kvTable.getTable().get("sendThreadPoolQueueSize")); 129 | this.startAcceptSendRequestTimeStamp = Long.parseLong(kvTable.getTable().get("startAcceptSendRequestTimeStamp")); 130 | this.putMessageEntireTimeMax = Long.parseLong(kvTable.getTable().get("putMessageEntireTimeMax")); 131 | this.earliestMessageTimeStamp = Long.parseLong(kvTable.getTable().get("earliestMessageTimeStamp")); 132 | this.remainTransientStoreBufferNumbs = Long.parseLong(kvTable.getTable().get("remainTransientStoreBufferNumbs")); 133 | this.queryThreadPoolQueueCapacity = Long.parseLong(kvTable.getTable().get("queryThreadPoolQueueCapacity")); 134 | this.putMessageAverageSize = Double.parseDouble(kvTable.getTable().get("putMessageAverageSize")); 135 | this.dispatchBehindBytes = Long.parseLong(kvTable.getTable().get("dispatchBehindBytes")); 136 | this.putMessageSizeTotal = Long.parseLong(kvTable.getTable().get("putMessageSizeTotal")); 137 | this.sendThreadPoolQueueCapacity = Long.parseLong(kvTable.getTable().get("sendThreadPoolQueueCapacity")); 138 | this.pullThreadPoolQueueCapacity = Long.parseLong(kvTable.getTable().get("pullThreadPoolQueueCapacity")); 139 | this.putLatency99 = Double.parseDouble(kvTable.getTable().getOrDefault("putLatency99", "-1")); 140 | this.putLatency999 = Double.parseDouble(kvTable.getTable().getOrDefault("putLatency999", "-1")); 141 | 142 | } 143 | 144 | private void loadCommitLogDirCapacity(String commitLogDirCapacity) { 145 | String[] arr = commitLogDirCapacity.split(" "); 146 | String total = String.format("%s %s", arr[2], arr[3].substring(0, arr[3].length() - 1)); 147 | String free = String.format("%s %s", arr[6], arr[7].substring(0, arr[7].length() - 1)); 148 | this.commitLogDirCapacityTotal = Utils.machineReadableByteCount(total); 149 | this.commitLogDirCapacityFree = Utils.machineReadableByteCount(free); 150 | } 151 | 152 | private void loadTps(PutTps putTps, String value) { 153 | String[] arr = value.split(" "); 154 | if (arr.length >= 1) { 155 | putTps.ten = Double.parseDouble(arr[0]); 156 | } 157 | if (arr.length >= 2) { 158 | putTps.sixty = Double.parseDouble(arr[1]); 159 | } 160 | if (arr.length >= 3) { 161 | putTps.sixHundred = Double.parseDouble(arr[2]); 162 | } 163 | 164 | } 165 | 166 | private void loadPutMessageDistributeTime(String str) { 167 | if ("null".equalsIgnoreCase(str)) { 168 | log.warn("loadPutMessageDistributeTime WARN, value is null"); 169 | return; 170 | } 171 | String[] arr = str.split(" "); 172 | String key = "", value = ""; 173 | for (String ar : arr) { 174 | String[] tarr = ar.split(":"); 175 | if (tarr.length < 2) { 176 | log.warn("loadPutMessageDistributeTime WARN, wrong value is {}, {}", ar, str); 177 | continue; 178 | } 179 | key = tarr[0].replace("[", "").replace("]", ""); 180 | value = tarr[1]; 181 | this.putMessageDistributeTimeMap.put(key, Integer.parseInt(value)); 182 | } 183 | } 184 | 185 | public void loadScheduleMessageOffsets(KVTable kvTable) { 186 | for (String key : kvTable.getTable().keySet()) { 187 | if (key.startsWith("scheduleMessageOffset")) { 188 | String[] arr = kvTable.getTable().get(key).split(","); 189 | ScheduleMessageOffsetTable table = new ScheduleMessageOffsetTable( 190 | Long.parseLong(arr[0]), 191 | Long.parseLong(arr[1]) 192 | ); 193 | this.scheduleMessageOffsetTables.add(table); 194 | } 195 | } 196 | } 197 | 198 | public static class ScheduleMessageOffsetTable { 199 | private long delayOffset; 200 | private long maxOffset; 201 | 202 | public ScheduleMessageOffsetTable(long first, long second) { 203 | this.delayOffset = first; 204 | this.maxOffset = second; 205 | } 206 | 207 | public long getDelayOffset() { 208 | return delayOffset; 209 | } 210 | 211 | public void setDelayOffset(long delayOffset) { 212 | this.delayOffset = delayOffset; 213 | } 214 | 215 | public long getMaxOffset() { 216 | return maxOffset; 217 | } 218 | 219 | public void setMaxOffset(long maxOffset) { 220 | this.maxOffset = maxOffset; 221 | } 222 | } 223 | 224 | public class PutTps { 225 | private double ten; 226 | private double sixty; 227 | private double sixHundred; 228 | 229 | public double getTen() { 230 | return ten; 231 | } 232 | 233 | public void setTen(double ten) { 234 | this.ten = ten; 235 | } 236 | 237 | public double getSixty() { 238 | return sixty; 239 | } 240 | 241 | public void setSixty(double sixty) { 242 | this.sixty = sixty; 243 | } 244 | 245 | public double getSixHundred() { 246 | return sixHundred; 247 | } 248 | 249 | public void setSixHundred(double sixHundred) { 250 | this.sixHundred = sixHundred; 251 | } 252 | } 253 | 254 | public class GetMissTps extends PutTps { 255 | } 256 | 257 | public class GetTransferedTps extends PutTps { 258 | } 259 | 260 | public class GetTotalTps extends PutTps { 261 | } 262 | 263 | public class GetFoundTps extends PutTps { 264 | } 265 | 266 | public long getMsgPutTotalTodayNow() { 267 | return msgPutTotalTodayNow; 268 | } 269 | 270 | public void setMsgPutTotalTodayNow(long msgPutTotalTodayNow) { 271 | this.msgPutTotalTodayNow = msgPutTotalTodayNow; 272 | } 273 | 274 | public long getMsgGetTotalTodayNow() { 275 | return msgGetTotalTodayNow; 276 | } 277 | 278 | public void setMsgGetTotalTodayNow(long msgGetTotalTodayNow) { 279 | this.msgGetTotalTodayNow = msgGetTotalTodayNow; 280 | } 281 | 282 | public long getMsgPutTotalTodayMorning() { 283 | return msgPutTotalTodayMorning; 284 | } 285 | 286 | public void setMsgPutTotalTodayMorning(long msgPutTotalTodayMorning) { 287 | this.msgPutTotalTodayMorning = msgPutTotalTodayMorning; 288 | } 289 | 290 | public long getMsgGetTotalTodayMorning() { 291 | return msgGetTotalTodayMorning; 292 | } 293 | 294 | public void setMsgGetTotalTodayMorning(long msgGetTotalTodayMorning) { 295 | this.msgGetTotalTodayMorning = msgGetTotalTodayMorning; 296 | } 297 | 298 | public long getMsgPutTotalYesterdayMorning() { 299 | return msgPutTotalYesterdayMorning; 300 | } 301 | 302 | public void setMsgPutTotalYesterdayMorning(long msgPutTotalYesterdayMorning) { 303 | this.msgPutTotalYesterdayMorning = msgPutTotalYesterdayMorning; 304 | } 305 | 306 | public long getMsgGetTotalYesterdayMorning() { 307 | return msgGetTotalYesterdayMorning; 308 | } 309 | 310 | public void setMsgGetTotalYesterdayMorning(long msgGetTotalYesterdayMorning) { 311 | this.msgGetTotalYesterdayMorning = msgGetTotalYesterdayMorning; 312 | } 313 | 314 | public List getScheduleMessageOffsetTables() { 315 | return scheduleMessageOffsetTables; 316 | } 317 | 318 | public void setScheduleMessageOffsetTables(List scheduleMessageOffsetTables) { 319 | this.scheduleMessageOffsetTables = scheduleMessageOffsetTables; 320 | } 321 | 322 | public long getSendThreadPoolQueueHeadWaitTimeMills() { 323 | return sendThreadPoolQueueHeadWaitTimeMills; 324 | } 325 | 326 | public void setSendThreadPoolQueueHeadWaitTimeMills(long sendThreadPoolQueueHeadWaitTimeMills) { 327 | this.sendThreadPoolQueueHeadWaitTimeMills = sendThreadPoolQueueHeadWaitTimeMills; 328 | } 329 | 330 | public long getQueryThreadPoolQueueHeadWaitTimeMills() { 331 | return queryThreadPoolQueueHeadWaitTimeMills; 332 | } 333 | 334 | public void setQueryThreadPoolQueueHeadWaitTimeMills(long queryThreadPoolQueueHeadWaitTimeMills) { 335 | this.queryThreadPoolQueueHeadWaitTimeMills = queryThreadPoolQueueHeadWaitTimeMills; 336 | } 337 | 338 | public long getPullThreadPoolQueueHeadWaitTimeMills() { 339 | return pullThreadPoolQueueHeadWaitTimeMills; 340 | } 341 | 342 | public void setPullThreadPoolQueueHeadWaitTimeMills(long pullThreadPoolQueueHeadWaitTimeMills) { 343 | this.pullThreadPoolQueueHeadWaitTimeMills = pullThreadPoolQueueHeadWaitTimeMills; 344 | } 345 | 346 | public long getQueryThreadPoolQueueSize() { 347 | return queryThreadPoolQueueSize; 348 | } 349 | 350 | public void setQueryThreadPoolQueueSize(long queryThreadPoolQueueSize) { 351 | this.queryThreadPoolQueueSize = queryThreadPoolQueueSize; 352 | } 353 | 354 | public long getPullThreadPoolQueueSize() { 355 | return pullThreadPoolQueueSize; 356 | } 357 | 358 | public void setPullThreadPoolQueueSize(long pullThreadPoolQueueSize) { 359 | this.pullThreadPoolQueueSize = pullThreadPoolQueueSize; 360 | } 361 | 362 | public long getSendThreadPoolQueueCapacity() { 363 | return sendThreadPoolQueueCapacity; 364 | } 365 | 366 | public void setSendThreadPoolQueueCapacity(long sendThreadPoolQueueCapacity) { 367 | this.sendThreadPoolQueueCapacity = sendThreadPoolQueueCapacity; 368 | } 369 | 370 | public long getPullThreadPoolQueueCapacity() { 371 | return pullThreadPoolQueueCapacity; 372 | } 373 | 374 | public void setPullThreadPoolQueueCapacity(long pullThreadPoolQueueCapacity) { 375 | this.pullThreadPoolQueueCapacity = pullThreadPoolQueueCapacity; 376 | } 377 | 378 | public Map getPutMessageDistributeTimeMap() { 379 | return putMessageDistributeTimeMap; 380 | } 381 | 382 | public void setPutMessageDistributeTimeMap(Map putMessageDistributeTimeMap) { 383 | this.putMessageDistributeTimeMap = putMessageDistributeTimeMap; 384 | } 385 | 386 | public double getRemainHowManyDataToFlush() { 387 | return remainHowManyDataToFlush; 388 | } 389 | 390 | public void setRemainHowManyDataToFlush(double remainHowManyDataToFlush) { 391 | this.remainHowManyDataToFlush = remainHowManyDataToFlush; 392 | } 393 | 394 | public long getCommitLogMinOffset() { 395 | return commitLogMinOffset; 396 | } 397 | 398 | public void setCommitLogMinOffset(long commitLogMinOffset) { 399 | this.commitLogMinOffset = commitLogMinOffset; 400 | } 401 | 402 | public long getCommitLogMaxOffset() { 403 | return commitLogMaxOffset; 404 | } 405 | 406 | public void setCommitLogMaxOffset(long commitLogMaxOffset) { 407 | this.commitLogMaxOffset = commitLogMaxOffset; 408 | } 409 | 410 | public String getRuntime() { 411 | return runtime; 412 | } 413 | 414 | public void setRuntime(String runtime) { 415 | this.runtime = runtime; 416 | } 417 | 418 | public long getBootTimestamp() { 419 | return bootTimestamp; 420 | } 421 | 422 | public void setBootTimestamp(long bootTimestamp) { 423 | this.bootTimestamp = bootTimestamp; 424 | } 425 | 426 | public double getCommitLogDirCapacityTotal() { 427 | return commitLogDirCapacityTotal; 428 | } 429 | 430 | public void setCommitLogDirCapacityTotal(double commitLogDirCapacityTotal) { 431 | this.commitLogDirCapacityTotal = commitLogDirCapacityTotal; 432 | } 433 | 434 | public double getCommitLogDirCapacityFree() { 435 | return commitLogDirCapacityFree; 436 | } 437 | 438 | public void setCommitLogDirCapacityFree(double commitLogDirCapacityFree) { 439 | this.commitLogDirCapacityFree = commitLogDirCapacityFree; 440 | } 441 | 442 | public int getBrokerVersion() { 443 | return brokerVersion; 444 | } 445 | 446 | public void setBrokerVersion(int brokerVersion) { 447 | this.brokerVersion = brokerVersion; 448 | } 449 | 450 | public long getDispatchMaxBuffer() { 451 | return dispatchMaxBuffer; 452 | } 453 | 454 | public void setDispatchMaxBuffer(long dispatchMaxBuffer) { 455 | this.dispatchMaxBuffer = dispatchMaxBuffer; 456 | } 457 | 458 | public PutTps getPutTps() { 459 | return putTps; 460 | } 461 | 462 | public void setPutTps(PutTps putTps) { 463 | this.putTps = putTps; 464 | } 465 | 466 | public GetMissTps getGetMissTps() { 467 | return getMissTps; 468 | } 469 | 470 | public void setGetMissTps(GetMissTps getMissTps) { 471 | this.getMissTps = getMissTps; 472 | } 473 | 474 | public GetTransferedTps getGetTransferedTps() { 475 | return getTransferedTps; 476 | } 477 | 478 | public void setGetTransferedTps(GetTransferedTps getTransferedTps) { 479 | this.getTransferedTps = getTransferedTps; 480 | } 481 | 482 | public GetTotalTps getGetTotalTps() { 483 | return getTotalTps; 484 | } 485 | 486 | public void setGetTotalTps(GetTotalTps getTotalTps) { 487 | this.getTotalTps = getTotalTps; 488 | } 489 | 490 | public GetFoundTps getGetFoundTps() { 491 | return getFoundTps; 492 | } 493 | 494 | public void setGetFoundTps(GetFoundTps getFoundTps) { 495 | this.getFoundTps = getFoundTps; 496 | } 497 | 498 | public double getConsumeQueueDiskRatio() { 499 | return consumeQueueDiskRatio; 500 | } 501 | 502 | public void setConsumeQueueDiskRatio(double consumeQueueDiskRatio) { 503 | this.consumeQueueDiskRatio = consumeQueueDiskRatio; 504 | } 505 | 506 | public double getCommitLogDiskRatio() { 507 | return commitLogDiskRatio; 508 | } 509 | 510 | public void setCommitLogDiskRatio(double commitLogDiskRatio) { 511 | this.commitLogDiskRatio = commitLogDiskRatio; 512 | } 513 | 514 | public long getPageCacheLockTimeMills() { 515 | return pageCacheLockTimeMills; 516 | } 517 | 518 | public void setPageCacheLockTimeMills(long pageCacheLockTimeMills) { 519 | this.pageCacheLockTimeMills = pageCacheLockTimeMills; 520 | } 521 | 522 | public long getGetMessageEntireTimeMax() { 523 | return getMessageEntireTimeMax; 524 | } 525 | 526 | public void setGetMessageEntireTimeMax(long getMessageEntireTimeMax) { 527 | this.getMessageEntireTimeMax = getMessageEntireTimeMax; 528 | } 529 | 530 | public long getPutMessageTimesTotal() { 531 | return putMessageTimesTotal; 532 | } 533 | 534 | public void setPutMessageTimesTotal(long putMessageTimesTotal) { 535 | this.putMessageTimesTotal = putMessageTimesTotal; 536 | } 537 | 538 | public String getBrokerVersionDesc() { 539 | return brokerVersionDesc; 540 | } 541 | 542 | public void setBrokerVersionDesc(String brokerVersionDesc) { 543 | this.brokerVersionDesc = brokerVersionDesc; 544 | } 545 | 546 | public long getSendThreadPoolQueueSize() { 547 | return sendThreadPoolQueueSize; 548 | } 549 | 550 | public void setSendThreadPoolQueueSize(long sendThreadPoolQueueSize) { 551 | this.sendThreadPoolQueueSize = sendThreadPoolQueueSize; 552 | } 553 | 554 | public long getStartAcceptSendRequestTimeStamp() { 555 | return startAcceptSendRequestTimeStamp; 556 | } 557 | 558 | public void setStartAcceptSendRequestTimeStamp(long startAcceptSendRequestTimeStamp) { 559 | this.startAcceptSendRequestTimeStamp = startAcceptSendRequestTimeStamp; 560 | } 561 | 562 | public long getPutMessageEntireTimeMax() { 563 | return putMessageEntireTimeMax; 564 | } 565 | 566 | public void setPutMessageEntireTimeMax(long putMessageEntireTimeMax) { 567 | this.putMessageEntireTimeMax = putMessageEntireTimeMax; 568 | } 569 | 570 | public long getEarliestMessageTimeStamp() { 571 | return earliestMessageTimeStamp; 572 | } 573 | 574 | public void setEarliestMessageTimeStamp(long earliestMessageTimeStamp) { 575 | this.earliestMessageTimeStamp = earliestMessageTimeStamp; 576 | } 577 | 578 | public long getRemainTransientStoreBufferNumbs() { 579 | return remainTransientStoreBufferNumbs; 580 | } 581 | 582 | public void setRemainTransientStoreBufferNumbs(long remainTransientStoreBufferNumbs) { 583 | this.remainTransientStoreBufferNumbs = remainTransientStoreBufferNumbs; 584 | } 585 | 586 | public long getQueryThreadPoolQueueCapacity() { 587 | return queryThreadPoolQueueCapacity; 588 | } 589 | 590 | public void setQueryThreadPoolQueueCapacity(long queryThreadPoolQueueCapacity) { 591 | this.queryThreadPoolQueueCapacity = queryThreadPoolQueueCapacity; 592 | } 593 | 594 | public double getPutMessageAverageSize() { 595 | return putMessageAverageSize; 596 | } 597 | 598 | public void setPutMessageAverageSize(double putMessageAverageSize) { 599 | this.putMessageAverageSize = putMessageAverageSize; 600 | } 601 | 602 | public long getPutMessageSizeTotal() { 603 | return putMessageSizeTotal; 604 | } 605 | 606 | public void setPutMessageSizeTotal(long putMessageSizeTotal) { 607 | this.putMessageSizeTotal = putMessageSizeTotal; 608 | } 609 | 610 | public long getDispatchBehindBytes() { 611 | return dispatchBehindBytes; 612 | } 613 | 614 | public void setDispatchBehindBytes(long dispatchBehindBytes) { 615 | this.dispatchBehindBytes = dispatchBehindBytes; 616 | } 617 | 618 | public double getPutLatency99() { 619 | return putLatency99; 620 | } 621 | 622 | public void setPutLatency99(double putLatency99) { 623 | this.putLatency99 = putLatency99; 624 | } 625 | 626 | public double getPutLatency999() { 627 | return putLatency999; 628 | } 629 | 630 | public void setPutLatency999(double putLatency999) { 631 | this.putLatency999 = putLatency999; 632 | } 633 | } 634 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/common/TwoTuple.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.common; 18 | 19 | public class TwoTuple { 20 | private T1 first; 21 | private T2 second; 22 | 23 | public TwoTuple(T1 first, T2 second) { 24 | this.first = first; 25 | this.second = second; 26 | } 27 | 28 | public T1 getFirst() { 29 | return first; 30 | } 31 | 32 | public T2 getSecond() { 33 | return second; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/BrokerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics; 18 | 19 | public class BrokerMetric { 20 | private String clusterName; 21 | private String brokerIP; 22 | private String brokerName; 23 | 24 | public BrokerMetric(String clusterName, String brokerIP, String brokerName) { 25 | this.clusterName = clusterName; 26 | this.brokerIP = brokerIP; 27 | this.brokerName = brokerName; 28 | } 29 | 30 | public String getClusterName() { 31 | return clusterName; 32 | } 33 | 34 | public void setClusterName(String clusterName) { 35 | this.clusterName = clusterName; 36 | } 37 | 38 | public String getBrokerIP() { 39 | return brokerIP; 40 | } 41 | 42 | public void setBrokerIP(String brokerIP) { 43 | this.brokerIP = brokerIP; 44 | } 45 | 46 | public String getBrokerName() { 47 | return brokerName; 48 | } 49 | 50 | public void setBrokerName(String brokerName) { 51 | this.brokerName = brokerName; 52 | } 53 | 54 | @Override 55 | public boolean equals(Object obj) { 56 | if (!(obj instanceof BrokerMetric)) { 57 | return false; 58 | } 59 | BrokerMetric other = (BrokerMetric) obj; 60 | 61 | return other.clusterName.equals(clusterName) && 62 | other.brokerIP.equals(brokerIP); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | int hash = 1; 68 | hash = 37 * hash + clusterName.hashCode(); 69 | hash = 37 * hash + brokerIP.hashCode(); 70 | return hash; 71 | } 72 | 73 | @Override 74 | public String toString() { 75 | return "ClusterName: " + clusterName + " brokerIP: " + brokerIP + " brokerHost: " + brokerName; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/ConsumerCountMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics; 18 | 19 | public class ConsumerCountMetric { 20 | private String caddrs; 21 | private String localaddrs; 22 | private String group; 23 | 24 | public ConsumerCountMetric(String group, String caddrs, String localaddrs) { 25 | this.caddrs = caddrs; 26 | this.localaddrs = localaddrs; 27 | this.group = group; 28 | } 29 | 30 | public String getCaddrs() { 31 | return caddrs; 32 | } 33 | 34 | public void setCaddrs(String caddrs) { 35 | this.caddrs = caddrs; 36 | } 37 | 38 | public String getLocaladdrs() { 39 | return localaddrs; 40 | } 41 | 42 | public void setLocaladdrs(String localaddrs) { 43 | this.localaddrs = localaddrs; 44 | } 45 | 46 | public String getGroup() { 47 | return group; 48 | } 49 | 50 | public void setGroup(String group) { 51 | this.group = group; 52 | } 53 | 54 | @Override 55 | public boolean equals(Object obj) { 56 | if (!(obj instanceof ConsumerCountMetric)) { 57 | return false; 58 | } 59 | ConsumerCountMetric other = (ConsumerCountMetric) obj; 60 | return other.group.equals(group); 61 | } 62 | 63 | @Override 64 | public int hashCode() { 65 | int hash = 1; 66 | hash = 37 * hash + group.hashCode(); 67 | return hash; 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return "group: " + group + " caddr: " + caddrs + " localaddr: " + localaddrs; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/ConsumerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics; 18 | 19 | public class ConsumerMetric { 20 | private String clusterName; 21 | private String brokerName; 22 | private String topicName; 23 | private String consumerGroupName; 24 | 25 | public ConsumerMetric(String clusterName, String brokerName, String topicName, String consumerGroupName) { 26 | this.clusterName = clusterName; 27 | this.brokerName = brokerName; 28 | this.topicName = topicName; 29 | this.consumerGroupName = consumerGroupName; 30 | } 31 | 32 | public String getTopicName() { 33 | return topicName; 34 | } 35 | 36 | public void setTopicName(String topicName) { 37 | this.topicName = topicName; 38 | } 39 | 40 | public String getConsumerGroupName() { 41 | return consumerGroupName; 42 | } 43 | 44 | public void setConsumerGroupName(String consumerGroupName) { 45 | this.consumerGroupName = consumerGroupName; 46 | } 47 | 48 | public String getClusterName() { 49 | return clusterName; 50 | } 51 | 52 | public void setClusterName(String clusterName) { 53 | this.clusterName = clusterName; 54 | } 55 | 56 | public String getBrokerName() { 57 | return brokerName; 58 | } 59 | 60 | public void setBrokerName(String brokerName) { 61 | this.brokerName = brokerName; 62 | } 63 | 64 | @Override 65 | public boolean equals(Object obj) { 66 | if (!(obj instanceof ConsumerMetric)) { 67 | return false; 68 | } 69 | ConsumerMetric other = (ConsumerMetric) obj; 70 | 71 | return other.clusterName.equals(clusterName) && other.brokerName.equals(brokerName) 72 | && other.topicName.equals(topicName) && other.consumerGroupName.equals(consumerGroupName); 73 | } 74 | 75 | @Override 76 | public int hashCode() { 77 | int hash = 1; 78 | hash = 37 * hash + clusterName.hashCode(); 79 | hash = 37 * hash + brokerName.hashCode(); 80 | hash = 37 * hash + topicName.hashCode(); 81 | hash = 37 * hash + consumerGroupName.hashCode(); 82 | return hash; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | return "clusterName: " + clusterName + "brokerName: " + brokerName 88 | + "topicName: " + topicName + " ConsumeGroupName: " + consumerGroupName; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/ConsumerTopicDiffMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics; 18 | 19 | public class ConsumerTopicDiffMetric { 20 | public ConsumerTopicDiffMetric(String group, String topic, String countOfOnlineConsumers, String msgModel) { 21 | this.group = group; 22 | this.topic = topic; 23 | this.countOfOnlineConsumers = countOfOnlineConsumers; 24 | this.msgModel = msgModel; 25 | } 26 | 27 | private String group; 28 | private String topic; 29 | private String countOfOnlineConsumers; 30 | private String msgModel; //0:broadcast, 1:cluster 31 | 32 | public String getGroup() { 33 | return group; 34 | } 35 | 36 | public void setGroup(String group) { 37 | this.group = group; 38 | } 39 | 40 | public String getTopic() { 41 | return topic; 42 | } 43 | 44 | public void setTopic(String topic) { 45 | this.topic = topic; 46 | } 47 | 48 | public String getCountOfOnlineConsumers() { 49 | return countOfOnlineConsumers; 50 | } 51 | 52 | public void setCountOfOnlineConsumers(String countOfOnlineConsumers) { 53 | this.countOfOnlineConsumers = countOfOnlineConsumers; 54 | } 55 | 56 | public String getMsgModel() { 57 | return msgModel; 58 | } 59 | 60 | public void setMsgModel(String msgModel) { 61 | this.msgModel = msgModel; 62 | } 63 | 64 | @Override 65 | public boolean equals(Object obj) { 66 | if (!(obj instanceof ConsumerTopicDiffMetric)) { 67 | return false; 68 | } 69 | ConsumerTopicDiffMetric other = (ConsumerTopicDiffMetric) obj; 70 | 71 | return other.group.equals(group) && 72 | other.topic.equals(topic) && 73 | other.countOfOnlineConsumers.equals(countOfOnlineConsumers) && 74 | other.msgModel.equals(msgModel); 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | int hash = 1; 80 | hash = 37 * hash + group.hashCode(); 81 | hash = 37 * hash + topic.hashCode(); 82 | hash = 37 * hash + countOfOnlineConsumers.hashCode(); 83 | hash = 37 * hash + msgModel.hashCode(); 84 | return hash; 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return "ConsumerGroup: " + group + " Topic: " + topic + " countOfOnlineConsumers: " + countOfOnlineConsumers 90 | + "msgModel: " + msgModel; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/DLQTopicOffsetMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics; 18 | 19 | public class DLQTopicOffsetMetric { 20 | private String clusterName; 21 | private String brokerName; 22 | private String group; 23 | private long lastUpdateTimestamp; 24 | 25 | public DLQTopicOffsetMetric(String clusterName, String brokerName, String group, long lastUpdateTimestamp) { 26 | this.clusterName = clusterName; 27 | this.brokerName = brokerName; 28 | this.group = group; 29 | this.lastUpdateTimestamp = lastUpdateTimestamp; 30 | } 31 | 32 | public String getClusterName() { 33 | return clusterName; 34 | } 35 | 36 | public void setClusterName(String clusterName) { 37 | this.clusterName = clusterName; 38 | } 39 | 40 | public String getBrokerName() { 41 | return brokerName; 42 | } 43 | 44 | public void setBrokerName(String brokerName) { 45 | this.brokerName = brokerName; 46 | } 47 | 48 | public String getGroup() { 49 | return group; 50 | } 51 | 52 | public void setGroup(String group) { 53 | this.group = group; 54 | } 55 | 56 | public long getLastUpdateTimestamp() { 57 | return lastUpdateTimestamp; 58 | } 59 | 60 | public void setLastUpdateTimestamp(long lastUpdateTimestamp) { 61 | this.lastUpdateTimestamp = lastUpdateTimestamp; 62 | } 63 | 64 | @Override 65 | public boolean equals(Object obj) { 66 | if (!(obj instanceof DLQTopicOffsetMetric)) { 67 | return false; 68 | } 69 | DLQTopicOffsetMetric other = (DLQTopicOffsetMetric) obj; 70 | 71 | return other.clusterName.equals(clusterName) && other.brokerName.equals(brokerName) && 72 | other.group.equals(group); 73 | 74 | } 75 | 76 | @Override 77 | public int hashCode() { 78 | int hash = 1; 79 | hash = 37 * hash + clusterName.hashCode(); 80 | hash = 37 * hash + brokerName.hashCode(); 81 | hash = 37 * hash + group.hashCode(); 82 | return hash; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | return "ClusterName: " + clusterName + " BrokerNames: " + brokerName + " group: " + group; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/TopicPutNumMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics; 18 | 19 | public class TopicPutNumMetric { 20 | private String clusterName; 21 | private String brokerName; 22 | private String brokerIP; 23 | private String topicName; 24 | 25 | public TopicPutNumMetric(String clusterName, String brokerName, String brokerIP, String topicName) { 26 | this.clusterName = clusterName; 27 | this.brokerName = brokerName; 28 | this.brokerIP = brokerIP; 29 | this.topicName = topicName; 30 | } 31 | 32 | public String getClusterName() { 33 | return clusterName; 34 | } 35 | 36 | public void setClusterName(String clusterName) { 37 | this.clusterName = clusterName; 38 | } 39 | 40 | public String getBrokerName() { 41 | return brokerName; 42 | } 43 | 44 | public void setBrokerName(String brokerName) { 45 | this.brokerName = brokerName; 46 | } 47 | 48 | public String getTopicName() { 49 | return topicName; 50 | } 51 | 52 | public void setTopicName(String topicName) { 53 | this.topicName = topicName; 54 | } 55 | 56 | public String getBrokerIP() { 57 | return brokerIP; 58 | } 59 | 60 | public void setBrokerIP(String brokerIP) { 61 | this.brokerIP = brokerIP; 62 | } 63 | 64 | @Override 65 | public boolean equals(Object obj) { 66 | if (!(obj instanceof TopicPutNumMetric)) { 67 | return false; 68 | } 69 | TopicPutNumMetric other = (TopicPutNumMetric) obj; 70 | 71 | return other.clusterName.equals(clusterName) && 72 | other.brokerIP.equals(brokerIP) && 73 | other.topicName.equals(topicName); 74 | } 75 | 76 | @Override 77 | public int hashCode() { 78 | int hash = 1; 79 | hash = 37 * hash + clusterName.hashCode(); 80 | hash = 37 * hash + topicName.hashCode(); 81 | hash = 37 * hash + brokerIP.hashCode(); 82 | return hash; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | return "ClusterName: " + clusterName + " brokerIP: " + brokerIP + " topicName: " + topicName; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/brokerruntime/BrokerRuntimeMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics.brokerruntime; 18 | 19 | public class BrokerRuntimeMetric { 20 | private String clusterName; 21 | private String brokerAddress; 22 | private String brokerHost; 23 | private String brokerDes; 24 | private long bootTimestamp; 25 | private int brokerVersion; 26 | 27 | public BrokerRuntimeMetric(String clusterName, String brokerAddress, String brokerHost, String brokerDes, long bootTimestamp, int brokerVersion) { 28 | this.clusterName = clusterName; 29 | this.brokerAddress = brokerAddress; 30 | this.brokerHost = brokerHost; 31 | this.brokerDes = brokerDes; 32 | this.bootTimestamp = bootTimestamp; 33 | this.brokerVersion = brokerVersion; 34 | } 35 | 36 | public String getClusterName() { 37 | return clusterName; 38 | } 39 | 40 | public void setClusterName(String clusterName) { 41 | this.clusterName = clusterName; 42 | } 43 | 44 | public String getBrokerAddress() { 45 | return brokerAddress; 46 | } 47 | 48 | public void setBrokerAddress(String brokerAddress) { 49 | this.brokerAddress = brokerAddress; 50 | } 51 | 52 | public String getBrokerHost() { 53 | return brokerHost; 54 | } 55 | 56 | public void setBrokerHost(String brokerHost) { 57 | this.brokerHost = brokerHost; 58 | } 59 | 60 | public String getBrokerDes() { 61 | return brokerDes; 62 | } 63 | 64 | public void setBrokerDes(String brokerDes) { 65 | this.brokerDes = brokerDes; 66 | } 67 | 68 | public long getBootTimestamp() { 69 | return bootTimestamp; 70 | } 71 | 72 | public void setBootTimestamp(long bootTimestamp) { 73 | this.bootTimestamp = bootTimestamp; 74 | } 75 | 76 | public int getBrokerVersion() { 77 | return brokerVersion; 78 | } 79 | 80 | public void setBrokerVersion(int brokerVersion) { 81 | this.brokerVersion = brokerVersion; 82 | } 83 | 84 | @Override 85 | public boolean equals(Object obj) { 86 | if (!(obj instanceof BrokerRuntimeMetric)) { 87 | return false; 88 | } 89 | BrokerRuntimeMetric other = (BrokerRuntimeMetric) obj; 90 | 91 | return other.clusterName.equals(clusterName) && 92 | other.brokerAddress.equals(brokerAddress); 93 | } 94 | 95 | @Override 96 | public int hashCode() { 97 | int hash = 1; 98 | hash = 37 * hash + clusterName.hashCode(); 99 | hash = 37 * hash + brokerAddress.hashCode(); 100 | return hash; 101 | } 102 | 103 | @Override 104 | public String toString() { 105 | return "ClusterName: " + clusterName + " brokerAddress: " + brokerAddress + " brokerHost: " + brokerHost; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/clientrunime/ConsumerRuntimeConsumeFailedMsgsMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics.clientrunime; 18 | 19 | public class ConsumerRuntimeConsumeFailedMsgsMetric { 20 | private String group; 21 | private String topic; 22 | private String caddrs; 23 | private String localaddrs; 24 | 25 | public ConsumerRuntimeConsumeFailedMsgsMetric(String group, String topic, String caddrs, String localaddrs) { 26 | this.group = group; 27 | this.topic = topic; 28 | this.caddrs = caddrs; 29 | this.localaddrs = localaddrs; 30 | } 31 | 32 | public String getGroup() { 33 | return group; 34 | } 35 | 36 | public void setGroup(String group) { 37 | this.group = group; 38 | } 39 | 40 | public String getTopic() { 41 | return topic; 42 | } 43 | 44 | public void setTopic(String topic) { 45 | this.topic = topic; 46 | } 47 | 48 | public String getCaddrs() { 49 | return caddrs; 50 | } 51 | 52 | public void setCaddrs(String caddrs) { 53 | this.caddrs = caddrs; 54 | } 55 | 56 | public String getLocaladdrs() { 57 | return localaddrs; 58 | } 59 | 60 | public void setLocaladdrs(String localaddrs) { 61 | this.localaddrs = localaddrs; 62 | } 63 | 64 | @Override 65 | public boolean equals(Object obj) { 66 | if (!(obj instanceof ConsumerRuntimeConsumeFailedMsgsMetric)) { 67 | return false; 68 | } 69 | ConsumerRuntimeConsumeFailedMsgsMetric other = (ConsumerRuntimeConsumeFailedMsgsMetric) obj; 70 | 71 | return other.group.equals(group) && 72 | other.topic.equals(topic) && 73 | other.getCaddrs().equalsIgnoreCase(caddrs); 74 | } 75 | 76 | @Override 77 | public int hashCode() { 78 | int hash = 1; 79 | hash = 37 * hash + group.hashCode(); 80 | hash = 37 * hash + topic.hashCode(); 81 | hash = 37 * hash + caddrs.hashCode(); 82 | return hash; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | return "group: " + group + " topic: " + topic + " caddrs: " + caddrs + " localaddrs: " + localaddrs; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/clientrunime/ConsumerRuntimeConsumeFailedTPSMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics.clientrunime; 18 | 19 | public class ConsumerRuntimeConsumeFailedTPSMetric extends ConsumerRuntimeConsumeFailedMsgsMetric { 20 | public ConsumerRuntimeConsumeFailedTPSMetric(String group, String topic, String caddrs, String localaddrs) { 21 | super(group, topic, caddrs, localaddrs); 22 | } 23 | 24 | @Override 25 | public int hashCode() { 26 | int hash = 1; 27 | hash = 37 * hash + this.getGroup().hashCode(); 28 | hash = 37 * hash + this.getTopic().hashCode(); 29 | hash = 37 * hash + this.getCaddrs().hashCode(); 30 | return hash; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "group: " + this.getGroup() + " topic: " + this.getTopic() + " caddrs: " + this.getCaddrs() + " localaddrs: " + this.getLocaladdrs(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/clientrunime/ConsumerRuntimeConsumeOKTPSMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics.clientrunime; 18 | 19 | public class ConsumerRuntimeConsumeOKTPSMetric extends ConsumerRuntimeConsumeFailedMsgsMetric { 20 | public ConsumerRuntimeConsumeOKTPSMetric(String group, String topic, String caddrs, String localaddrs) { 21 | super(group, topic, caddrs, localaddrs); 22 | } 23 | 24 | @Override 25 | public int hashCode() { 26 | int hash = 1; 27 | hash = 37 * hash + this.getGroup().hashCode(); 28 | hash = 37 * hash + this.getTopic().hashCode(); 29 | hash = 37 * hash + this.getCaddrs().hashCode(); 30 | return hash; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "group: " + this.getGroup() + " topic: " + this.getTopic() + " caddrs: " + this.getCaddrs() + " localaddrs: " + this.getLocaladdrs(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/clientrunime/ConsumerRuntimeConsumeRTMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics.clientrunime; 18 | 19 | public class ConsumerRuntimeConsumeRTMetric extends ConsumerRuntimeConsumeFailedMsgsMetric { 20 | public ConsumerRuntimeConsumeRTMetric(String group, String topic, String caddrs, String localaddrs) { 21 | super(group, topic, caddrs, localaddrs); 22 | } 23 | 24 | @Override 25 | public int hashCode() { 26 | int hash = 1; 27 | hash = 37 * hash + this.getGroup().hashCode(); 28 | hash = 37 * hash + this.getTopic().hashCode(); 29 | hash = 37 * hash + this.getCaddrs().hashCode(); 30 | return hash; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "group: " + this.getGroup() + " topic: " + this.getTopic() + " caddrs: " + this.getCaddrs() + " localaddrs: " + this.getLocaladdrs(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/clientrunime/ConsumerRuntimePullRTMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics.clientrunime; 18 | 19 | public class ConsumerRuntimePullRTMetric extends ConsumerRuntimeConsumeFailedMsgsMetric { 20 | public ConsumerRuntimePullRTMetric(String group, String topic, String caddrs, String localaddrs) { 21 | super(group, topic, caddrs, localaddrs); 22 | } 23 | 24 | @Override 25 | public int hashCode() { 26 | int hash = 1; 27 | hash = 37 * hash + this.getGroup().hashCode(); 28 | hash = 37 * hash + this.getTopic().hashCode(); 29 | hash = 37 * hash + this.getCaddrs().hashCode(); 30 | return hash; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "group: " + this.getGroup() + " topic: " + this.getTopic() + " caddrs: " + this.getCaddrs() + " localaddrs: " + this.getLocaladdrs(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/clientrunime/ConsumerRuntimePullTPSMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics.clientrunime; 18 | 19 | public class ConsumerRuntimePullTPSMetric extends ConsumerRuntimeConsumeFailedMsgsMetric { 20 | public ConsumerRuntimePullTPSMetric(String group, String topic, String caddrs, String localaddrs) { 21 | super(group, topic, caddrs, localaddrs); 22 | } 23 | 24 | @Override 25 | public int hashCode() { 26 | int hash = 1; 27 | hash = 37 * hash + this.getGroup().hashCode(); 28 | hash = 37 * hash + this.getTopic().hashCode(); 29 | hash = 37 * hash + this.getCaddrs().hashCode(); 30 | return hash; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "group: " + this.getGroup() + " topic: " + this.getTopic() + " caddrs: " + this.getCaddrs() + " localaddrs: " + this.getLocaladdrs(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/producer/ProducerCountMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics.producer; 18 | 19 | public class ProducerCountMetric { 20 | private String clusterName; 21 | private String brokerName; 22 | private String group; 23 | 24 | public ProducerCountMetric(String clusterName, String brokerName, String group) { 25 | this.clusterName = clusterName; 26 | this.brokerName = brokerName; 27 | this.group = group; 28 | } 29 | 30 | @Override 31 | public boolean equals(Object obj) { 32 | if (!(obj instanceof ProducerCountMetric)) { 33 | return false; 34 | } 35 | ProducerCountMetric other = (ProducerCountMetric) obj; 36 | return other.group.equals(this.group) && other.clusterName.equals(this.clusterName) && other.brokerName.equals(this.brokerName); 37 | } 38 | 39 | @Override 40 | public int hashCode() { 41 | int hash = 1; 42 | hash = 37 * hash + group.hashCode(); 43 | return hash; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "group: " + group + 49 | " brokerName: " + brokerName + 50 | " clusterName: " + clusterName; 51 | } 52 | 53 | public String getClusterName() { 54 | return clusterName; 55 | } 56 | 57 | public String getBrokerName() { 58 | return brokerName; 59 | } 60 | 61 | public String getGroup() { 62 | return group; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/model/metrics/producer/ProducerMetric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.model.metrics.producer; 18 | 19 | //max offset of topic 20 | public class ProducerMetric { 21 | private String clusterName; 22 | private String brokerName; 23 | private String topicName; 24 | private long lastUpdateTimestamp; 25 | 26 | public String getClusterName() { 27 | return clusterName; 28 | } 29 | 30 | public void setClusterName(String clusterName) { 31 | this.clusterName = clusterName; 32 | } 33 | 34 | public String getBrokerName() { 35 | return brokerName; 36 | } 37 | 38 | public void setBrokerName(String brokerName) { 39 | this.brokerName = brokerName; 40 | } 41 | 42 | public String getTopicName() { 43 | return topicName; 44 | } 45 | 46 | public void setTopicName(String topicName) { 47 | this.topicName = topicName; 48 | } 49 | 50 | public long getLastUpdateTimestamp() { 51 | return lastUpdateTimestamp; 52 | } 53 | 54 | public void setLastUpdateTimestamp(long lastUpdateTimestamp) { 55 | this.lastUpdateTimestamp = lastUpdateTimestamp; 56 | } 57 | 58 | public ProducerMetric(String clusterName, String brokerName, String topicName, long lastUpdateTimestamp) { 59 | this.clusterName = clusterName; 60 | this.brokerName = brokerName; 61 | this.topicName = topicName; 62 | this.lastUpdateTimestamp = lastUpdateTimestamp; 63 | } 64 | 65 | @Override 66 | public boolean equals(Object obj) { 67 | if (!(obj instanceof ProducerMetric)) { 68 | return false; 69 | } 70 | ProducerMetric other = (ProducerMetric) obj; 71 | 72 | return other.clusterName.equals(clusterName) && other.brokerName.equals(brokerName) && 73 | other.topicName.equals(topicName); 74 | } 75 | 76 | @Override 77 | public int hashCode() { 78 | int hash = 1; 79 | hash = 37 * hash + clusterName.hashCode(); 80 | hash = 37 * hash + brokerName.hashCode(); 81 | hash = 37 * hash + topicName.hashCode(); 82 | return hash; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | return "ClusterName: " + clusterName + " BrokerName: " + brokerName + " topicName: " + topicName; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/otlp/OtlpGrpcLauncher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.otlp; 18 | 19 | import javax.annotation.PostConstruct; 20 | import io.grpc.Server; 21 | import io.grpc.ServerBuilder; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.beans.factory.annotation.Value; 26 | import org.springframework.stereotype.Component; 27 | 28 | @Component 29 | public class OtlpGrpcLauncher { 30 | 31 | private Logger log = LoggerFactory.getLogger(OtlpGrpcLauncher.class); 32 | 33 | private Server server; 34 | 35 | @Value("${grpc.server.port}") 36 | private Integer grpcServerPort; 37 | 38 | @Autowired 39 | OtlpMetricsCollectorService otlpMetricsCollectorService; 40 | 41 | @PostConstruct 42 | public void start() throws Exception { 43 | try { 44 | server = ServerBuilder.forPort(grpcServerPort) 45 | .addService(otlpMetricsCollectorService) 46 | .build().start(); 47 | log.info("grpc server start successfully at " + grpcServerPort); 48 | Runtime.getRuntime().addShutdownHook(new Thread(this::stop)); 49 | } catch (Exception e) { 50 | log.error("grpc server start failed.", e); 51 | throw e; 52 | } 53 | } 54 | 55 | private void stop() { 56 | if (server != null) { 57 | server.shutdownNow(); 58 | log.info("grpc server shutdown successfully."); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/otlp/OtlpMetricsCollectorService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.otlp; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import io.grpc.stub.StreamObserver; 23 | import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest; 24 | import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse; 25 | import io.opentelemetry.proto.collector.metrics.v1.MetricsServiceGrpc; 26 | import io.opentelemetry.proto.common.v1.KeyValue; 27 | import io.opentelemetry.proto.metrics.v1.HistogramDataPoint; 28 | import io.opentelemetry.proto.metrics.v1.Metric; 29 | import io.opentelemetry.proto.metrics.v1.NumberDataPoint; 30 | import io.opentelemetry.proto.metrics.v1.NumberDataPoint.ValueCase; 31 | import io.opentelemetry.proto.metrics.v1.ResourceMetrics; 32 | import io.opentelemetry.proto.metrics.v1.ScopeMetrics; 33 | import io.prometheus.client.Collector.MetricFamilySamples; 34 | import io.prometheus.client.Collector.MetricFamilySamples.Sample; 35 | import io.prometheus.client.Collector.Type; 36 | import org.apache.rocketmq.exporter.model.common.TwoTuple; 37 | import org.slf4j.Logger; 38 | import org.slf4j.LoggerFactory; 39 | import org.springframework.stereotype.Service; 40 | 41 | @Service 42 | public class OtlpMetricsCollectorService extends MetricsServiceGrpc.MetricsServiceImplBase { 43 | 44 | private final List otlpMfs = new ArrayList<>(); 45 | 46 | private static final String LABEL_BUCKET_BOUND = "le"; 47 | 48 | private final static Logger log = LoggerFactory.getLogger(OtlpMetricsCollectorService.class); 49 | 50 | @Override 51 | public void export(ExportMetricsServiceRequest request, 52 | StreamObserver responseObserver) { 53 | log.info("receive oltp metrics export request..."); 54 | try { 55 | List newMfs = new ArrayList<>(); 56 | collectMetrics(request, newMfs); 57 | synchronized (otlpMfs) { 58 | otlpMfs.clear(); 59 | otlpMfs.addAll(newMfs); 60 | } 61 | } catch (Exception e) { 62 | log.error("Unexpected error when exporting otlp metrics, request={}", request, e); 63 | responseObserver.onError(e); 64 | } 65 | responseObserver.onNext(ExportMetricsServiceResponse.getDefaultInstance()); 66 | responseObserver.onCompleted(); 67 | } 68 | 69 | public void collectOtlpMetrics(List mfs) { 70 | synchronized (otlpMfs) { 71 | mfs.addAll(otlpMfs); 72 | } 73 | } 74 | 75 | private void collectMetrics(ExportMetricsServiceRequest request, List mfs) { 76 | final List resourceMetricsList = request.getResourceMetricsList(); 77 | for (ResourceMetrics resourceMetrics : resourceMetricsList) { 78 | final List scopeMetricsList = resourceMetrics.getScopeMetricsList(); 79 | for (ScopeMetrics scopeMetrics : scopeMetricsList) { 80 | final List metricList = scopeMetrics.getMetricsList(); 81 | for (Metric metric : metricList) { 82 | String name = metric.getName(); 83 | switch (metric.getDataCase()) { 84 | case GAUGE: { 85 | final List pointList = metric.getGauge().getDataPointsList(); 86 | List samples = new ArrayList<>(); 87 | for (NumberDataPoint point : pointList) { 88 | TwoTuple, List> labelNamesAndValues = getLabelNamesAndValues(point.getAttributesList()); 89 | double pointValue = ValueCase.AS_DOUBLE == point.getValueCase() ? point.getAsDouble() : point.getAsInt(); 90 | Sample sample = new Sample(name, labelNamesAndValues.getFirst(), labelNamesAndValues.getSecond(), pointValue); 91 | samples.add(sample); 92 | } 93 | MetricFamilySamples metricFamily = new MetricFamilySamples(name, Type.GAUGE, name, samples); 94 | mfs.add(metricFamily); 95 | break; 96 | } 97 | case SUM: { 98 | final List pointList = metric.getSum().getDataPointsList(); 99 | List samples = new ArrayList<>(); 100 | for (NumberDataPoint point : pointList) { 101 | TwoTuple, List> labelNamesAndValues = getLabelNamesAndValues(point.getAttributesList()); 102 | double pointValue = ValueCase.AS_DOUBLE == point.getValueCase() ? point.getAsDouble() : point.getAsInt(); 103 | Sample sample = new Sample(name, labelNamesAndValues.getFirst(), labelNamesAndValues.getSecond(), pointValue); 104 | samples.add(sample); 105 | } 106 | MetricFamilySamples metricFamily = new MetricFamilySamples(name, Type.COUNTER, name, samples); 107 | mfs.add(metricFamily); 108 | break; 109 | } 110 | case HISTOGRAM: { 111 | final List pointList = metric.getHistogram().getDataPointsList(); 112 | List samples = new ArrayList<>(); 113 | for (HistogramDataPoint point : pointList) { 114 | TwoTuple, List> labelNamesAndValues = getLabelNamesAndValues(point.getAttributesList()); 115 | List labelNames = labelNamesAndValues.getFirst(); 116 | List labelValues = labelNamesAndValues.getSecond(); 117 | int boundCount = point.getExplicitBoundsList().size(); 118 | for (int i = 0; i < boundCount; i++) { 119 | Double bound = point.getExplicitBoundsList().get(i); 120 | List keys = new ArrayList<>(labelNames); 121 | keys.add(LABEL_BUCKET_BOUND); 122 | List values = new ArrayList<>(labelValues); 123 | values.add(String.valueOf(bound)); 124 | Long count = point.getBucketCountsList().get(i); 125 | Sample sample = new Sample(name + "_bucket", keys, values, count); 126 | samples.add(sample); 127 | } 128 | List keys = new ArrayList<>(labelNames); 129 | keys.add(LABEL_BUCKET_BOUND); 130 | List values = new ArrayList<>(labelValues); 131 | values.add("+Inf"); 132 | Long count = point.getBucketCountsList().get(boundCount); 133 | Sample sample = new Sample(name + "_bucket", keys, values, count); 134 | samples.add(sample); 135 | // count 136 | samples.add(new Sample(name + "_count", labelNames, labelValues, point.getCount())); 137 | // sum 138 | samples.add(new Sample(name + "_sum", labelNames, labelValues, point.getSum())); 139 | } 140 | MetricFamilySamples metricFamily = new MetricFamilySamples(name, Type.HISTOGRAM, name, samples); 141 | mfs.add(metricFamily); 142 | break; 143 | } 144 | default: 145 | break; 146 | } 147 | } 148 | } 149 | } 150 | } 151 | 152 | private TwoTuple, List> getLabelNamesAndValues(List attributesList) { 153 | List labelNames = new ArrayList<>(); 154 | List labelValues = new ArrayList<>(); 155 | for (KeyValue keyValue : attributesList) { 156 | String key = keyValue.getKey(); 157 | String value = keyValue.getValue().getStringValue(); 158 | labelNames.add(key); 159 | labelValues.add(value); 160 | } 161 | return new TwoTuple<>(labelNames, labelValues); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/service/RMQMetricsService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.service; 18 | 19 | import org.apache.rocketmq.exporter.collector.RMQMetricsCollector; 20 | 21 | import java.io.IOException; 22 | import java.io.StringWriter; 23 | 24 | 25 | public interface RMQMetricsService { 26 | RMQMetricsCollector getCollector(); 27 | 28 | void metrics(StringWriter writer) throws IOException; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/service/client/MQAdminExtImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.service.client; 18 | 19 | import com.google.common.base.Throwables; 20 | import org.apache.rocketmq.client.QueryResult; 21 | import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer; 22 | import org.apache.rocketmq.client.consumer.PullResult; 23 | import org.apache.rocketmq.client.exception.MQBrokerException; 24 | import org.apache.rocketmq.client.exception.MQClientException; 25 | import org.apache.rocketmq.client.impl.MQAdminImpl; 26 | import org.apache.rocketmq.client.impl.factory.MQClientInstance; 27 | import org.apache.rocketmq.common.AclConfig; 28 | import org.apache.rocketmq.common.PlainAccessConfig; 29 | import org.apache.rocketmq.common.TopicConfig; 30 | import org.apache.rocketmq.common.admin.ConsumeStats; 31 | import org.apache.rocketmq.common.admin.RollbackStats; 32 | import org.apache.rocketmq.common.admin.TopicStatsTable; 33 | import org.apache.rocketmq.common.message.MessageClientIDSetter; 34 | import org.apache.rocketmq.common.message.MessageExt; 35 | import org.apache.rocketmq.common.message.MessageQueue; 36 | import org.apache.rocketmq.common.protocol.RequestCode; 37 | import org.apache.rocketmq.common.protocol.ResponseCode; 38 | import org.apache.rocketmq.common.protocol.body.BrokerStatsData; 39 | import org.apache.rocketmq.common.protocol.body.ClusterAclVersionInfo; 40 | import org.apache.rocketmq.common.protocol.body.ClusterInfo; 41 | import org.apache.rocketmq.common.protocol.body.ConsumeMessageDirectlyResult; 42 | import org.apache.rocketmq.common.protocol.body.ConsumeStatsList; 43 | import org.apache.rocketmq.common.protocol.body.ConsumerConnection; 44 | import org.apache.rocketmq.common.protocol.body.ConsumerRunningInfo; 45 | import org.apache.rocketmq.common.protocol.body.GroupList; 46 | import org.apache.rocketmq.common.protocol.body.KVTable; 47 | import org.apache.rocketmq.common.protocol.body.ProducerConnection; 48 | import org.apache.rocketmq.common.protocol.body.ProducerTableInfo; 49 | import org.apache.rocketmq.common.protocol.body.QueryConsumeQueueResponseBody; 50 | import org.apache.rocketmq.common.protocol.body.QueueTimeSpan; 51 | import org.apache.rocketmq.common.protocol.body.SubscriptionGroupWrapper; 52 | import org.apache.rocketmq.common.protocol.body.TopicConfigSerializeWrapper; 53 | import org.apache.rocketmq.common.protocol.body.TopicList; 54 | import org.apache.rocketmq.common.protocol.route.TopicRouteData; 55 | import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig; 56 | import org.apache.rocketmq.exporter.util.JsonUtil; 57 | import org.apache.rocketmq.remoting.RemotingClient; 58 | import org.apache.rocketmq.remoting.exception.RemotingCommandException; 59 | import org.apache.rocketmq.remoting.exception.RemotingConnectException; 60 | import org.apache.rocketmq.remoting.exception.RemotingException; 61 | import org.apache.rocketmq.remoting.exception.RemotingSendRequestException; 62 | import org.apache.rocketmq.remoting.exception.RemotingTimeoutException; 63 | import org.apache.rocketmq.remoting.protocol.RemotingCommand; 64 | import org.apache.rocketmq.tools.admin.DefaultMQAdminExt; 65 | import org.apache.rocketmq.tools.admin.MQAdminExt; 66 | import org.apache.rocketmq.tools.admin.api.MessageTrack; 67 | import org.joor.Reflect; 68 | import org.slf4j.Logger; 69 | import org.slf4j.LoggerFactory; 70 | import org.springframework.beans.factory.annotation.Autowired; 71 | import org.springframework.beans.factory.annotation.Qualifier; 72 | import org.springframework.stereotype.Service; 73 | 74 | import java.io.UnsupportedEncodingException; 75 | import java.util.List; 76 | import java.util.Map; 77 | import java.util.Properties; 78 | import java.util.Set; 79 | 80 | import static org.apache.rocketmq.remoting.protocol.RemotingSerializable.decode; 81 | 82 | @Service("mqAdminExtImpl") 83 | public class MQAdminExtImpl implements MQAdminExt { 84 | @Autowired 85 | @Qualifier("defaultMQAdminExt") 86 | private DefaultMQAdminExt defaultMQAdminExt; 87 | 88 | @Autowired 89 | private DefaultMQPullConsumer pullConsumer; 90 | 91 | @Autowired 92 | private RemotingClient remotingClient; 93 | 94 | @Autowired 95 | private MQClientInstance mqClientInstance; 96 | 97 | private Logger logger = LoggerFactory.getLogger(MQAdminExtImpl.class); 98 | 99 | public MQAdminExtImpl() { 100 | } 101 | 102 | 103 | public PullResult queryMsgByOffset(MessageQueue mq, long offset) throws Exception { 104 | return pullConsumer.pull(mq, "*", offset, 1); 105 | } 106 | 107 | @Override 108 | public void updateBrokerConfig(String brokerAddr, Properties properties) 109 | throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, 110 | UnsupportedEncodingException, InterruptedException, MQBrokerException { 111 | defaultMQAdminExt.updateBrokerConfig(brokerAddr, properties); 112 | } 113 | 114 | @Override 115 | public void createAndUpdateTopicConfig(String addr, TopicConfig config) 116 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 117 | defaultMQAdminExt.createAndUpdateTopicConfig(addr, config); 118 | } 119 | 120 | @Override 121 | public void createAndUpdatePlainAccessConfig(String addr, 122 | PlainAccessConfig plainAccessConfig) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 123 | //ignore 124 | } 125 | 126 | @Override 127 | public void deletePlainAccessConfig(String addr, 128 | String accessKey) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 129 | //ignore 130 | } 131 | 132 | @Override 133 | public void updateGlobalWhiteAddrConfig(String addr, 134 | String globalWhiteAddrs) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 135 | //ignore 136 | } 137 | 138 | @Override 139 | public void updateGlobalWhiteAddrConfig(final String addr, final String globalWhiteAddrs, String aclFileFullPath)throws RemotingException, MQBrokerException, 140 | InterruptedException, MQClientException{ 141 | //ignore 142 | } 143 | 144 | @Override 145 | public ClusterAclVersionInfo examineBrokerClusterAclVersionInfo( 146 | String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 147 | //ignore 148 | return null; 149 | } 150 | 151 | @Override 152 | public AclConfig examineBrokerClusterAclConfig( 153 | String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 154 | //ignore 155 | return null; 156 | } 157 | 158 | @Override 159 | public void createAndUpdateSubscriptionGroupConfig(String addr, SubscriptionGroupConfig config) 160 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 161 | defaultMQAdminExt.createAndUpdateSubscriptionGroupConfig(addr, config); 162 | } 163 | 164 | @Override 165 | public SubscriptionGroupConfig examineSubscriptionGroupConfig(String addr, String group) { 166 | RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_SUBSCRIPTIONGROUP_CONFIG, null); 167 | RemotingCommand response = null; 168 | try { 169 | response = remotingClient.invokeSync(addr, request, 3000); 170 | } catch (Exception err) { 171 | throw Throwables.propagate(err); 172 | } 173 | assert response != null; 174 | switch (response.getCode()) { 175 | case ResponseCode.SUCCESS: { 176 | SubscriptionGroupWrapper subscriptionGroupWrapper = decode(response.getBody(), SubscriptionGroupWrapper.class); 177 | return subscriptionGroupWrapper.getSubscriptionGroupTable().get(group); 178 | } 179 | default: 180 | throw Throwables.propagate(new MQBrokerException(response.getCode(), response.getRemark())); 181 | } 182 | } 183 | 184 | @Override 185 | public TopicConfig examineTopicConfig(String addr, String topic) { 186 | RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_TOPIC_CONFIG, null); 187 | RemotingCommand response = null; 188 | try { 189 | response = remotingClient.invokeSync(addr, request, 3000); 190 | } catch (Exception err) { 191 | throw Throwables.propagate(err); 192 | } 193 | switch (response.getCode()) { 194 | case ResponseCode.SUCCESS: { 195 | TopicConfigSerializeWrapper topicConfigSerializeWrapper = decode(response.getBody(), TopicConfigSerializeWrapper.class); 196 | return topicConfigSerializeWrapper.getTopicConfigTable().get(topic); 197 | } 198 | default: 199 | throw Throwables.propagate(new MQBrokerException(response.getCode(), response.getRemark())); 200 | } 201 | } 202 | 203 | @Override 204 | public TopicStatsTable examineTopicStats(String topic) 205 | throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 206 | return defaultMQAdminExt.examineTopicStats(topic); 207 | } 208 | 209 | @Override 210 | public TopicList fetchAllTopicList() throws RemotingException, MQClientException, InterruptedException { 211 | TopicList topicList = defaultMQAdminExt.fetchAllTopicList(); 212 | logger.debug("op=look={}", JsonUtil.obj2String(topicList.getTopicList())); 213 | return topicList; 214 | } 215 | 216 | @Override 217 | public KVTable fetchBrokerRuntimeStats(String brokerAddr) 218 | throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, 219 | InterruptedException, MQBrokerException { 220 | return defaultMQAdminExt.fetchBrokerRuntimeStats(brokerAddr); 221 | } 222 | 223 | @Override 224 | public ConsumeStats examineConsumeStats(String consumerGroup) 225 | throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 226 | return defaultMQAdminExt.examineConsumeStats(consumerGroup); 227 | } 228 | 229 | @Override 230 | public ConsumeStats examineConsumeStats(String consumerGroup, String topic) 231 | throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 232 | return defaultMQAdminExt.examineConsumeStats(consumerGroup, topic); 233 | } 234 | 235 | @Override 236 | public ClusterInfo examineBrokerClusterInfo() 237 | throws InterruptedException, MQBrokerException, RemotingTimeoutException, RemotingSendRequestException, 238 | RemotingConnectException { 239 | return defaultMQAdminExt.examineBrokerClusterInfo(); 240 | } 241 | 242 | @Override 243 | public TopicRouteData examineTopicRouteInfo(String topic) 244 | throws RemotingException, MQClientException, InterruptedException { 245 | return defaultMQAdminExt.examineTopicRouteInfo(topic); 246 | } 247 | 248 | @Override 249 | public ConsumerConnection examineConsumerConnectionInfo(String consumerGroup) 250 | throws 251 | InterruptedException, MQBrokerException, RemotingException, MQClientException { 252 | return defaultMQAdminExt.examineConsumerConnectionInfo(consumerGroup); 253 | } 254 | 255 | @Override 256 | public ConsumerConnection examineConsumerConnectionInfo(String consumerGroup, String brokerAddr) throws InterruptedException, MQBrokerException, RemotingException, MQClientException { 257 | return defaultMQAdminExt.examineConsumerConnectionInfo(consumerGroup, brokerAddr); 258 | } 259 | 260 | @Override 261 | public ProducerConnection examineProducerConnectionInfo(String producerGroup, String topic) 262 | throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 263 | return defaultMQAdminExt.examineProducerConnectionInfo(producerGroup, topic); 264 | } 265 | 266 | // add @4.9.4 267 | @Override 268 | public ProducerTableInfo getAllProducerInfo(String brokerAddr) throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 269 | return this.defaultMQAdminExt.getAllProducerInfo(brokerAddr); 270 | } 271 | 272 | @Override 273 | public List getNameServerAddressList() { 274 | return defaultMQAdminExt.getNameServerAddressList(); 275 | } 276 | 277 | @Override 278 | public int wipeWritePermOfBroker(String namesrvAddr, String brokerName) 279 | throws RemotingCommandException, RemotingConnectException, RemotingSendRequestException, 280 | RemotingTimeoutException, InterruptedException, MQClientException { 281 | return defaultMQAdminExt.wipeWritePermOfBroker(namesrvAddr, brokerName); 282 | } 283 | 284 | @Override 285 | public int addWritePermOfBroker(String namesrvAddr, String brokerName) throws RemotingCommandException, RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, InterruptedException, MQClientException { 286 | // ignore 287 | return 0; 288 | } 289 | 290 | @Override 291 | public void putKVConfig(String namespace, String key, String value) { 292 | defaultMQAdminExt.putKVConfig(namespace, key, value); 293 | } 294 | 295 | @Override 296 | public String getKVConfig(String namespace, String key) 297 | throws RemotingException, MQClientException, InterruptedException { 298 | return defaultMQAdminExt.getKVConfig(namespace, key); 299 | } 300 | 301 | @Override 302 | public KVTable getKVListByNamespace(String namespace) 303 | throws RemotingException, MQClientException, InterruptedException { 304 | return defaultMQAdminExt.getKVListByNamespace(namespace); 305 | } 306 | 307 | @Override 308 | public void deleteTopicInBroker(Set addrs, String topic) 309 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 310 | logger.info("addrs={} topic={}", JsonUtil.obj2String(addrs), topic); 311 | defaultMQAdminExt.deleteTopicInBroker(addrs, topic); 312 | } 313 | 314 | @Override 315 | public void deleteTopicInNameServer(Set addrs, String topic, String clusterName) 316 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 317 | defaultMQAdminExt.deleteTopicInNameServer(addrs, topic, clusterName); 318 | } 319 | 320 | @Override 321 | public void deleteSubscriptionGroup(String addr, String groupName) 322 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 323 | //ignore 324 | } 325 | 326 | @Override 327 | public void deleteSubscriptionGroup(String addr, String groupName, boolean removeOffset) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 328 | 329 | } 330 | 331 | @Override 332 | public void createAndUpdateKvConfig(String namespace, String key, String value) 333 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 334 | defaultMQAdminExt.createAndUpdateKvConfig(namespace, key, value); 335 | } 336 | 337 | @Override 338 | public void deleteKvConfig(String namespace, String key) 339 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 340 | defaultMQAdminExt.deleteKvConfig(namespace, key); 341 | } 342 | 343 | @Override 344 | public List resetOffsetByTimestampOld(String consumerGroup, String topic, long timestamp, 345 | boolean force) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 346 | return defaultMQAdminExt.resetOffsetByTimestampOld(consumerGroup, topic, timestamp, force); 347 | } 348 | 349 | @Override 350 | public Map resetOffsetByTimestamp(String topic, String group, long timestamp, 351 | boolean isForce) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 352 | return defaultMQAdminExt.resetOffsetByTimestamp(topic, group, timestamp, isForce); 353 | } 354 | 355 | @Override 356 | public void resetOffsetNew(String consumerGroup, String topic, long timestamp) 357 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 358 | defaultMQAdminExt.resetOffsetNew(consumerGroup, topic, timestamp); 359 | } 360 | 361 | @Override 362 | public Map> getConsumeStatus(String topic, String group, 363 | String clientAddr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 364 | return defaultMQAdminExt.getConsumeStatus(topic, group, clientAddr); 365 | } 366 | 367 | @Override 368 | public void createOrUpdateOrderConf(String key, String value, boolean isCluster) 369 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 370 | defaultMQAdminExt.createOrUpdateOrderConf(key, value, isCluster); 371 | } 372 | 373 | @Override 374 | public GroupList queryTopicConsumeByWho(String topic) 375 | throws 376 | InterruptedException, MQBrokerException, RemotingException, MQClientException { 377 | return defaultMQAdminExt.queryTopicConsumeByWho(topic); 378 | } 379 | 380 | @Override 381 | public boolean cleanExpiredConsumerQueue(String cluster) 382 | throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, 383 | InterruptedException { 384 | return defaultMQAdminExt.cleanExpiredConsumerQueue(cluster); 385 | } 386 | 387 | @Override 388 | public boolean cleanExpiredConsumerQueueByAddr(String addr) 389 | throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, 390 | InterruptedException { 391 | return defaultMQAdminExt.cleanExpiredConsumerQueueByAddr(addr); 392 | } 393 | 394 | @Override 395 | public boolean deleteExpiredCommitLog(String cluster) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException { 396 | return false; 397 | } 398 | 399 | @Override 400 | public boolean deleteExpiredCommitLogByAddr(String addr) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException { 401 | return false; 402 | } 403 | 404 | @Override 405 | public ConsumerRunningInfo getConsumerRunningInfo(String consumerGroup, String clientId, boolean jstack) 406 | throws RemotingException, MQClientException, InterruptedException { 407 | return defaultMQAdminExt.getConsumerRunningInfo(consumerGroup, clientId, jstack); 408 | } 409 | 410 | @Override 411 | public ConsumeMessageDirectlyResult consumeMessageDirectly(String consumerGroup, String clientId, 412 | String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 413 | return defaultMQAdminExt.consumeMessageDirectly(consumerGroup, clientId, msgId); 414 | } 415 | 416 | @Override 417 | public List messageTrackDetail(MessageExt msg) 418 | throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 419 | return defaultMQAdminExt.messageTrackDetail(msg); 420 | } 421 | 422 | @Override 423 | public void cloneGroupOffset(String srcGroup, String destGroup, String topic, boolean isOffline) 424 | throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 425 | defaultMQAdminExt.cloneGroupOffset(srcGroup, destGroup, topic, isOffline); 426 | } 427 | 428 | @Override 429 | public void createTopic(String key, String newTopic, int queueNum) throws MQClientException { 430 | defaultMQAdminExt.createTopic(key, newTopic, queueNum); 431 | } 432 | 433 | @Override 434 | public void createTopic(String key, String newTopic, int queueNum, int topicSysFlag) 435 | throws MQClientException { 436 | defaultMQAdminExt.createTopic(key, newTopic, queueNum, topicSysFlag); 437 | } 438 | 439 | @Override 440 | public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException { 441 | return defaultMQAdminExt.searchOffset(mq, timestamp); 442 | } 443 | 444 | @Override 445 | public long maxOffset(MessageQueue mq) throws MQClientException { 446 | return defaultMQAdminExt.maxOffset(mq); 447 | } 448 | 449 | @Override 450 | public long minOffset(MessageQueue mq) throws MQClientException { 451 | return defaultMQAdminExt.minOffset(mq); 452 | } 453 | 454 | @Override 455 | public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException { 456 | return defaultMQAdminExt.earliestMsgStoreTime(mq); 457 | } 458 | 459 | @Override 460 | public MessageExt viewMessage(String msgId) 461 | throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 462 | return defaultMQAdminExt.viewMessage(msgId); 463 | } 464 | 465 | @Override 466 | public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) 467 | throws MQClientException, InterruptedException { 468 | return defaultMQAdminExt.queryMessage(topic, key, maxNum, begin, end); 469 | } 470 | 471 | @Override 472 | @Deprecated 473 | public void start() throws MQClientException { 474 | throw new IllegalStateException("thisMethod is deprecated.use org.apache.rocketmq.console.aspect.admin.MQAdminAspect instead of this"); 475 | } 476 | 477 | @Override 478 | @Deprecated 479 | public void shutdown() { 480 | throw new IllegalStateException("thisMethod is deprecated.use org.apache.rocketmq.console.aspect.admin.MQAdminAspect instead of this"); 481 | } 482 | 483 | // below is 3.2.6->3.5.8 updated 484 | 485 | @Override 486 | public List queryConsumeTimeSpan(String topic, 487 | String group) throws InterruptedException, MQBrokerException, RemotingException, MQClientException { 488 | return defaultMQAdminExt.queryConsumeTimeSpan(topic, group); 489 | } 490 | 491 | //MessageClientIDSetter.getNearlyTimeFromID has bug,so we subtract half a day 492 | //next version we will remove it 493 | //https://issues.apache.org/jira/browse/ROCKETMQ-111 494 | //https://github.com/apache/incubator-rocketmq/pull/69 495 | @Override 496 | public MessageExt viewMessage(String topic, 497 | String msgId) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { 498 | logger.info("MessageClientIDSetter.getNearlyTimeFromID(msgId)={} msgId={}", MessageClientIDSetter.getNearlyTimeFromID(msgId), msgId); 499 | try { 500 | return viewMessage(msgId); 501 | } catch (Exception e) { 502 | } 503 | MQAdminImpl mqAdminImpl = mqClientInstance.getMQAdminImpl(); 504 | QueryResult qr = Reflect.on(mqAdminImpl).call("queryMessage", topic, msgId, 32, 505 | MessageClientIDSetter.getNearlyTimeFromID(msgId).getTime() - 1000 * 60 * 60 * 13L, Long.MAX_VALUE, true).get(); 506 | if (qr != null && qr.getMessageList() != null && qr.getMessageList().size() > 0) { 507 | return qr.getMessageList().get(0); 508 | } else { 509 | return null; 510 | } 511 | } 512 | 513 | @Override 514 | public ConsumeMessageDirectlyResult consumeMessageDirectly(String consumerGroup, String clientId, String topic, 515 | String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 516 | return defaultMQAdminExt.consumeMessageDirectly(consumerGroup, clientId, topic, msgId); 517 | } 518 | 519 | @Override 520 | public Properties getBrokerConfig( 521 | String brokerAddr) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, UnsupportedEncodingException, InterruptedException, MQBrokerException { 522 | return defaultMQAdminExt.getBrokerConfig(brokerAddr); 523 | } 524 | 525 | @Override 526 | public TopicList fetchTopicsByCLuster( 527 | String clusterName) throws RemotingException, MQClientException, InterruptedException { 528 | return defaultMQAdminExt.fetchTopicsByCLuster(clusterName); 529 | } 530 | 531 | @Override 532 | public boolean cleanUnusedTopic( 533 | String cluster) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException { 534 | return defaultMQAdminExt.cleanUnusedTopic(cluster); 535 | } 536 | 537 | @Override 538 | public boolean cleanUnusedTopicByAddr( 539 | String addr) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException { 540 | return defaultMQAdminExt.cleanUnusedTopicByAddr(addr); 541 | } 542 | 543 | @Override 544 | public BrokerStatsData viewBrokerStatsData(String brokerAddr, String statsName, 545 | String statsKey) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException { 546 | return defaultMQAdminExt.viewBrokerStatsData(brokerAddr, statsName, statsKey); 547 | } 548 | 549 | @Override 550 | public Set getClusterList( 551 | String topic) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException { 552 | return defaultMQAdminExt.getClusterList(topic); 553 | } 554 | 555 | @Override 556 | public ConsumeStatsList fetchConsumeStatsInBroker(String brokerAddr, boolean isOrder, 557 | long timeoutMillis) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException { 558 | return defaultMQAdminExt.fetchConsumeStatsInBroker(brokerAddr, isOrder, timeoutMillis); 559 | } 560 | 561 | @Override 562 | public Set getTopicClusterList( 563 | String topic) throws InterruptedException, MQBrokerException, MQClientException, RemotingException { 564 | return defaultMQAdminExt.getTopicClusterList(topic); 565 | } 566 | 567 | @Override 568 | public SubscriptionGroupWrapper getAllSubscriptionGroup(String brokerAddr, 569 | long timeoutMillis) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQBrokerException { 570 | return defaultMQAdminExt.getAllSubscriptionGroup(brokerAddr, timeoutMillis); 571 | } 572 | 573 | @Override 574 | public SubscriptionGroupWrapper getUserSubscriptionGroup(String brokerAddr, long timeoutMillis) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQBrokerException { 575 | return this.defaultMQAdminExt.getUserSubscriptionGroup(brokerAddr, timeoutMillis); 576 | } 577 | 578 | @Override 579 | public TopicConfigSerializeWrapper getAllTopicConfig(String brokerAddr, long timeoutMillis) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQBrokerException { 580 | return this.defaultMQAdminExt.getAllTopicConfig(brokerAddr, timeoutMillis); 581 | } 582 | 583 | @Override 584 | public TopicConfigSerializeWrapper getUserTopicConfig(String brokerAddr, boolean specialTopic, long timeoutMillis) throws InterruptedException, RemotingException, MQBrokerException, MQClientException { 585 | return this.defaultMQAdminExt.getUserTopicConfig(brokerAddr, specialTopic, timeoutMillis); 586 | } 587 | 588 | @Override 589 | public void updateConsumeOffset(String brokerAddr, String consumeGroup, MessageQueue mq, 590 | long offset) throws RemotingException, InterruptedException, MQBrokerException { 591 | defaultMQAdminExt.updateConsumeOffset(brokerAddr, consumeGroup, mq, offset); 592 | } 593 | 594 | // 4.0.0 added 595 | @Override 596 | public void updateNameServerConfig(Properties properties, 597 | List list) throws InterruptedException, RemotingConnectException, UnsupportedEncodingException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, MQBrokerException { 598 | this.defaultMQAdminExt.updateNameServerConfig(properties, list); 599 | } 600 | 601 | @Override 602 | public Map getNameServerConfig( 603 | List list) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQClientException, UnsupportedEncodingException { 604 | return this.defaultMQAdminExt.getNameServerConfig(list); 605 | } 606 | 607 | @Override 608 | public QueryConsumeQueueResponseBody queryConsumeQueue(String brokerAddr, String topic, 609 | int queueId, long index, int count, 610 | String consumerGroup) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQClientException { 611 | return this.defaultMQAdminExt.queryConsumeQueue(brokerAddr, topic, queueId, index, count, consumerGroup); 612 | } 613 | 614 | @Override 615 | public boolean resumeCheckHalfMessage( 616 | String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 617 | return false; 618 | } 619 | 620 | @Override 621 | public boolean resumeCheckHalfMessage(String topic, 622 | String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException { 623 | return false; 624 | } 625 | } 626 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/service/client/MQAdminInstance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.service.client; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | import org.apache.rocketmq.acl.common.AclClientRPCHook; 21 | import org.apache.rocketmq.acl.common.SessionCredentials; 22 | import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer; 23 | import org.apache.rocketmq.client.exception.MQClientException; 24 | import org.apache.rocketmq.client.impl.MQClientAPIImpl; 25 | import org.apache.rocketmq.client.impl.factory.MQClientInstance; 26 | import org.apache.rocketmq.common.MixAll; 27 | import org.apache.rocketmq.exporter.config.RMQConfigure; 28 | import org.apache.rocketmq.remoting.RPCHook; 29 | import org.apache.rocketmq.remoting.RemotingClient; 30 | import org.apache.rocketmq.tools.admin.DefaultMQAdminExt; 31 | import org.apache.rocketmq.tools.admin.DefaultMQAdminExtImpl; 32 | import org.joor.Reflect; 33 | import org.slf4j.Logger; 34 | import org.slf4j.LoggerFactory; 35 | import org.springframework.beans.factory.annotation.Autowired; 36 | import org.springframework.beans.factory.annotation.Qualifier; 37 | import org.springframework.context.annotation.Bean; 38 | import org.springframework.stereotype.Service; 39 | 40 | import static org.apache.rocketmq.common.MixAll.TOOLS_CONSUMER_GROUP; 41 | 42 | @Service 43 | public class MQAdminInstance { 44 | private final static Logger log = LoggerFactory.getLogger(MQAdminInstance.class); 45 | @Autowired 46 | private RMQConfigure configure; 47 | private RPCHook aclHook; 48 | 49 | private MQAdminInstance(RMQConfigure configure) { 50 | this.configure = configure; 51 | aclHook = getAclRPCHook(); 52 | } 53 | 54 | private RPCHook getAclRPCHook() { 55 | if (configure.enableACL()) { 56 | if (StringUtils.isAllBlank(configure.getAccessKey())) { 57 | throw new RuntimeException("acl config error: accessKey is empty"); 58 | } 59 | if (StringUtils.isAllBlank(configure.getSecretKey())) { 60 | throw new RuntimeException("acl config error: secretKey is empty"); 61 | } 62 | return new AclClientRPCHook(new SessionCredentials(configure.getAccessKey(), configure.getSecretKey())); 63 | } 64 | return null; 65 | } 66 | 67 | @Bean(destroyMethod = "shutdown", name = "defaultMQAdminExt") 68 | private DefaultMQAdminExt buildDefaultMQAdminExt() throws Exception { 69 | String namesrvAddress = configure.getNamesrvAddr(); 70 | if (StringUtils.isBlank(namesrvAddress)) { 71 | log.error("Build DefaultMQAdminExt error, namesrv is null"); 72 | throw new Exception("Build DefaultMQAdminExt error, namesrv is null", null); 73 | } 74 | DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(this.aclHook,5000L); 75 | defaultMQAdminExt.setInstanceName("admin-" + System.currentTimeMillis()); 76 | defaultMQAdminExt.setNamesrvAddr(namesrvAddress); 77 | try { 78 | defaultMQAdminExt.start(); 79 | } catch (MQClientException ex) { 80 | log.error(String.format("init default admin error, namesrv=%s", System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY)), ex); 81 | } 82 | return defaultMQAdminExt; 83 | } 84 | 85 | @Bean(destroyMethod = "shutdown") 86 | private DefaultMQPullConsumer buildPullConsumer() throws Exception { 87 | String namesrvAddress = configure.getNamesrvAddr(); 88 | if (StringUtils.isBlank(namesrvAddress)) { 89 | log.error("init default pull consumer error, namesrv is null"); 90 | throw new Exception("init default pull consumer error, namesrv is null", null); 91 | } 92 | DefaultMQPullConsumer pullConsumer = new DefaultMQPullConsumer(TOOLS_CONSUMER_GROUP, this.aclHook); 93 | pullConsumer.setInstanceName("consumer-" + System.currentTimeMillis()); 94 | pullConsumer.setNamesrvAddr(namesrvAddress); 95 | try { 96 | pullConsumer.start(); 97 | pullConsumer.getDefaultMQPullConsumerImpl().getPullAPIWrapper().setConnectBrokerByUser(true); 98 | } catch (MQClientException ex) { 99 | log.error(String.format("init default pull consumer error, namesrv=%s", System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY)), ex); 100 | } 101 | return pullConsumer; 102 | } 103 | 104 | @Bean(destroyMethod = "shutdown") 105 | private MQClientInstance buildInstance(@Qualifier("defaultMQAdminExt") DefaultMQAdminExt defaultMQAdminExt) { 106 | DefaultMQAdminExtImpl defaultMQAdminExtImpl = Reflect.on(defaultMQAdminExt).get("defaultMQAdminExtImpl"); 107 | return Reflect.on(defaultMQAdminExtImpl).get("mqClientInstance"); 108 | } 109 | 110 | @Bean 111 | private RemotingClient client(MQClientInstance instance) { 112 | MQClientAPIImpl mQClientAPIImpl = Reflect.on(instance).get("mQClientAPIImpl"); 113 | return Reflect.on(mQClientAPIImpl).get("remotingClient"); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/service/impl/RMQMetricsServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.service.impl; 18 | 19 | import io.prometheus.client.Collector; 20 | import io.prometheus.client.CollectorRegistry; 21 | import org.apache.rocketmq.exporter.collector.RMQMetricsCollector; 22 | import org.apache.rocketmq.exporter.config.RMQConfigure; 23 | import org.apache.rocketmq.exporter.otlp.OtlpMetricsCollectorService; 24 | import org.apache.rocketmq.exporter.service.RMQMetricsService; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.stereotype.Service; 27 | 28 | import java.io.IOException; 29 | import java.io.StringWriter; 30 | import java.io.Writer; 31 | import java.util.Enumeration; 32 | import java.util.Iterator; 33 | 34 | import javax.annotation.PostConstruct; 35 | 36 | @Service 37 | public class RMQMetricsServiceImpl implements RMQMetricsService { 38 | @Autowired 39 | private RMQConfigure configure; 40 | 41 | private CollectorRegistry registry = new CollectorRegistry(); 42 | private final RMQMetricsCollector rmqMetricsCollector; 43 | 44 | @Autowired 45 | private OtlpMetricsCollectorService otlpMetricsCollectorService; 46 | 47 | @Override 48 | public RMQMetricsCollector getCollector() { 49 | return rmqMetricsCollector; 50 | } 51 | 52 | public RMQMetricsServiceImpl(RMQConfigure configure) { 53 | this.configure = configure; 54 | rmqMetricsCollector = new RMQMetricsCollector(configure.getOutOfTimeSeconds()); 55 | rmqMetricsCollector.register(registry); 56 | } 57 | 58 | @PostConstruct 59 | public void init() { 60 | rmqMetricsCollector.setOtlpMetricsCollectorService(otlpMetricsCollectorService); 61 | } 62 | 63 | @Override 64 | public void metrics(StringWriter writer) throws IOException { 65 | this.writeEscapedHelp(writer, registry.metricFamilySamples()); 66 | } 67 | 68 | public void writeEscapedHelp(Writer writer, Enumeration mfs) throws IOException { 69 | while (mfs.hasMoreElements()) { 70 | Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement(); 71 | for (Iterator var3 = metricFamilySamples.samples.iterator(); var3.hasNext(); writer.write(10)) { 72 | Collector.MetricFamilySamples.Sample sample = (Collector.MetricFamilySamples.Sample) var3.next(); 73 | writer.write(sample.name); 74 | if (sample.labelNames.size() > 0) { 75 | writer.write(123); 76 | 77 | for (int i = 0; i < sample.labelNames.size(); ++i) { 78 | writer.write((String) sample.labelNames.get(i)); 79 | writer.write("=\""); 80 | writeEscapedLabelValue(writer, (String) sample.labelValues.get(i)); 81 | writer.write("\","); 82 | } 83 | 84 | writer.write(125); 85 | } 86 | 87 | writer.write(32); 88 | writer.write(Collector.doubleToGoString(sample.value)); 89 | if (sample.timestampMs != null) { 90 | writer.write(32); 91 | writer.write(sample.timestampMs.toString()); 92 | } 93 | } 94 | } 95 | 96 | } 97 | 98 | private static void writeEscapedLabelValue(Writer writer, String s) throws IOException { 99 | for (int i = 0; i < s.length(); ++i) { 100 | char c = s.charAt(i); 101 | switch (c) { 102 | case '\n': 103 | writer.append("\\n"); 104 | break; 105 | case '"': 106 | writer.append("\\\""); 107 | break; 108 | case '\\': 109 | writer.append("\\\\"); 110 | break; 111 | default: 112 | writer.append(c); 113 | } 114 | } 115 | 116 | } 117 | 118 | private static String typeString(Collector.Type t) { 119 | switch (t) { 120 | case GAUGE: 121 | return "gauge"; 122 | case COUNTER: 123 | return "counter"; 124 | case SUMMARY: 125 | return "summary"; 126 | case HISTOGRAM: 127 | return "histogram"; 128 | default: 129 | return "untyped"; 130 | } 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/task/ClientMetricCollectorFixedThreadPoolExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.task; 18 | 19 | import java.util.concurrent.BlockingQueue; 20 | import java.util.concurrent.RejectedExecutionHandler; 21 | import java.util.concurrent.RunnableFuture; 22 | import java.util.concurrent.ThreadFactory; 23 | import java.util.concurrent.ThreadPoolExecutor; 24 | import java.util.concurrent.TimeUnit; 25 | import java.util.concurrent.FutureTask; 26 | 27 | public class ClientMetricCollectorFixedThreadPoolExecutor extends ThreadPoolExecutor { 28 | public ClientMetricCollectorFixedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, 29 | long keepAliveTime, TimeUnit unit, 30 | BlockingQueue workQueue, ThreadFactory threadFactory, 31 | RejectedExecutionHandler handler) { 32 | super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); 33 | } 34 | 35 | 36 | protected RunnableFuture newTaskFor(Runnable runnable, T value) { 37 | return new FutureTask(runnable, value); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/task/ClientMetricTaskRunnable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.task; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | import org.apache.rocketmq.client.exception.MQClientException; 21 | import org.apache.rocketmq.common.protocol.body.Connection; 22 | import org.apache.rocketmq.common.protocol.body.ConsumerConnection; 23 | import org.apache.rocketmq.common.protocol.body.ConsumerRunningInfo; 24 | import org.apache.rocketmq.exporter.service.RMQMetricsService; 25 | import org.apache.rocketmq.remoting.exception.RemotingException; 26 | import org.apache.rocketmq.tools.admin.MQAdminExt; 27 | import org.slf4j.Logger; 28 | 29 | public class ClientMetricTaskRunnable implements Runnable { 30 | private String consumerGroup; 31 | private ConsumerConnection connection; 32 | private boolean enableCollectJStack; 33 | private MQAdminExt mqAdmin; 34 | private Logger logger; 35 | private RMQMetricsService metricsService; 36 | 37 | public ClientMetricTaskRunnable(String consumerGroup, ConsumerConnection connection, 38 | boolean enableCollectJStack, MQAdminExt mqAdmin, Logger logger, 39 | RMQMetricsService metricsService) { 40 | this.consumerGroup = consumerGroup; 41 | this.connection = connection; 42 | this.enableCollectJStack = enableCollectJStack; 43 | this.mqAdmin = mqAdmin; 44 | this.logger = logger; 45 | this.metricsService = metricsService; 46 | } 47 | 48 | @Override 49 | 50 | public void run() { 51 | if (this.connection == null || this.connection.getConnectionSet() == null || 52 | this.connection.getConnectionSet().isEmpty()) { 53 | return; 54 | } 55 | logger.debug(String.format("ClientMetricTask-group=%s,enable jstack=%s", 56 | consumerGroup, 57 | this.enableCollectJStack 58 | 59 | )); 60 | long start = System.currentTimeMillis(); 61 | ConsumerRunningInfo runningInfo = null; 62 | for (Connection conn : this.connection.getConnectionSet()) { 63 | try { 64 | runningInfo = mqAdmin.getConsumerRunningInfo(this.consumerGroup, conn.getClientId(), this.enableCollectJStack); 65 | } catch (InterruptedException | RemotingException e) { 66 | logger.warn(String.format("ClientMetricTask-exception.ignore. group=%s,client id=%s, client addr=%s, language=%s,version=%d", 67 | consumerGroup, 68 | conn.getClientId(), 69 | conn.getClientAddr(), 70 | conn.getLanguage(), 71 | conn.getVersion() 72 | ), 73 | e); 74 | runningInfo = null; 75 | } catch (MQClientException e) { 76 | logger.warn(String.format("ClientMetricTask-exception.ignore. group=%s,client id=%s, client addr=%s, language=%s,version=%d, error code=%d, error msg=%s", 77 | consumerGroup, 78 | conn.getClientId(), 79 | conn.getClientAddr(), 80 | conn.getLanguage(), 81 | conn.getVersion(), 82 | e.getResponseCode(), 83 | e.getErrorMessage()) 84 | ); 85 | runningInfo = null; 86 | } 87 | if (runningInfo == null) { 88 | continue; 89 | } 90 | if (!StringUtils.isBlank(runningInfo.getJstack())) { 91 | logger.error(String.format("group=%s, jstack=%s", consumerGroup, runningInfo.getJstack())); 92 | } 93 | if (runningInfo.getStatusTable() != null && !runningInfo.getStatusTable().isEmpty()) { 94 | for (String topic : runningInfo.getStatusTable().keySet()) { 95 | metricsService.getCollector().addConsumerClientFailedMsgCountsMetric( 96 | this.consumerGroup, 97 | topic, 98 | conn.getClientAddr(), 99 | conn.getClientId(), 100 | runningInfo.getStatusTable().get(topic).getConsumeFailedMsgs()); 101 | metricsService.getCollector().addConsumerClientFailedTPSMetric( 102 | this.consumerGroup, 103 | topic, 104 | conn.getClientAddr(), 105 | conn.getClientId(), 106 | runningInfo.getStatusTable().get(topic).getConsumeFailedTPS()); 107 | metricsService.getCollector().addConsumerClientOKTPSMetric( 108 | this.consumerGroup, 109 | topic, 110 | conn.getClientAddr(), 111 | conn.getClientId(), 112 | runningInfo.getStatusTable().get(topic).getConsumeOKTPS()); 113 | metricsService.getCollector().addConsumeRTMetricMetric( 114 | this.consumerGroup, 115 | topic, 116 | conn.getClientAddr(), 117 | conn.getClientId(), 118 | runningInfo.getStatusTable().get(topic).getConsumeRT()); 119 | metricsService.getCollector().addPullRTMetric( 120 | this.consumerGroup, 121 | topic, 122 | conn.getClientAddr(), 123 | conn.getClientId(), 124 | runningInfo.getStatusTable().get(topic).getPullRT()); 125 | metricsService.getCollector().addPullTPSMetric( 126 | this.consumerGroup, 127 | topic, 128 | conn.getClientAddr(), 129 | conn.getClientId(), 130 | runningInfo.getStatusTable().get(topic).getPullTPS()); 131 | 132 | 133 | } 134 | 135 | } 136 | } 137 | long cost = System.currentTimeMillis() - start; 138 | logger.debug(String.format("one-ClientMetricTask-group=%s, cost=%d, online-instance count=%d", this.consumerGroup, cost, this.connection.getConnectionSet().size())); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.rocketmq.exporter.util; 19 | 20 | import com.fasterxml.jackson.annotation.JsonInclude; 21 | import com.fasterxml.jackson.core.type.TypeReference; 22 | import com.fasterxml.jackson.databind.DeserializationFeature; 23 | import com.fasterxml.jackson.databind.ObjectMapper; 24 | import com.fasterxml.jackson.databind.SerializationFeature; 25 | import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; 26 | import com.google.common.base.Strings; 27 | import com.google.common.base.Throwables; 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | import java.io.IOException; 32 | import java.io.Writer; 33 | import java.text.SimpleDateFormat; 34 | import java.util.Map; 35 | 36 | @SuppressWarnings("unchecked") 37 | public class JsonUtil { 38 | 39 | private static Logger logger = LoggerFactory.getLogger(JsonUtil.class); 40 | private static ObjectMapper objectMapper = new ObjectMapper(); 41 | 42 | private JsonUtil() { 43 | } 44 | 45 | static { 46 | objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 47 | objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); 48 | objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 49 | objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 50 | objectMapper.setFilterProvider(new SimpleFilterProvider().setFailOnUnknownId(false)); 51 | objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); 52 | objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); 53 | } 54 | 55 | public static void writeValue(Writer writer, Object obj) { 56 | try { 57 | objectMapper.writeValue(writer, obj); 58 | } catch (IOException e) { 59 | Throwables.propagateIfPossible(e); 60 | } 61 | } 62 | 63 | public static String obj2String(T src) { 64 | if (src == null) { 65 | return null; 66 | } 67 | 68 | try { 69 | return src instanceof String ? (String) src : objectMapper.writeValueAsString(src); 70 | } catch (Exception e) { 71 | logger.error("Parse Object to String error src=" + src, e); 72 | return null; 73 | } 74 | } 75 | 76 | public static byte[] obj2Byte(T src) { 77 | if (src == null) { 78 | return null; 79 | } 80 | 81 | try { 82 | return src instanceof byte[] ? (byte[]) src : objectMapper.writeValueAsBytes(src); 83 | } catch (Exception e) { 84 | logger.error("Parse Object to byte[] error", e); 85 | return null; 86 | } 87 | } 88 | 89 | public static T string2Obj(String str, Class clazz) { 90 | if (Strings.isNullOrEmpty(str) || clazz == null) { 91 | return null; 92 | } 93 | str = escapesSpecialChar(str); 94 | try { 95 | return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz); 96 | } catch (Exception e) { 97 | logger.error("Parse String to Object error\nString: {}\nClass: {}\nError: {}", str, clazz.getName(), e); 98 | return null; 99 | } 100 | } 101 | 102 | public static T byte2Obj(byte[] bytes, Class clazz) { 103 | if (bytes == null || clazz == null) { 104 | return null; 105 | } 106 | try { 107 | return clazz.equals(byte[].class) ? (T) bytes : objectMapper.readValue(bytes, clazz); 108 | } catch (Exception e) { 109 | logger.error("Parse byte[] to Object error\nbyte[]: {}\nClass: {}\nError: {}", bytes, clazz.getName(), e); 110 | return null; 111 | } 112 | } 113 | 114 | public static T string2Obj(String str, TypeReference typeReference) { 115 | if (Strings.isNullOrEmpty(str) || typeReference == null) { 116 | return null; 117 | } 118 | str = escapesSpecialChar(str); 119 | try { 120 | return (T) (typeReference.getType().equals(String.class) ? str : objectMapper.readValue(str, typeReference)); 121 | } catch (Exception e) { 122 | logger.error("Parse String to Object error\nString: {}\nTypeReference: {}\nError: {}", str, 123 | typeReference.getType(), e); 124 | return null; 125 | } 126 | } 127 | 128 | public static T byte2Obj(byte[] bytes, TypeReference typeReference) { 129 | if (bytes == null || typeReference == null) { 130 | return null; 131 | } 132 | try { 133 | return (T) (typeReference.getType().equals(byte[].class) ? bytes : objectMapper.readValue(bytes, 134 | typeReference)); 135 | } catch (Exception e) { 136 | logger.error("Parse byte[] to Object error\nbyte[]: {}\nTypeReference: {}\nError: {}", bytes, 137 | typeReference.getType(), e); 138 | return null; 139 | } 140 | } 141 | 142 | public static T map2Obj(Map map, Class clazz) { 143 | String str = obj2String(map); 144 | return string2Obj(str, clazz); 145 | } 146 | 147 | private static String escapesSpecialChar(String str) { 148 | return str.replace("\n", "\\n").replace("\r", "\\r"); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/org/apache/rocketmq/exporter/util/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.rocketmq.exporter.util; 19 | 20 | import java.text.DecimalFormat; 21 | 22 | public class Utils { 23 | public static double getFixedDouble(double value) { 24 | DecimalFormat df = new DecimalFormat("#.##"); 25 | return new Double(df.format(value)); 26 | } 27 | 28 | public static double machineReadableByteCount(String humanReadableValue) { 29 | int unitSize = 1024; 30 | String[] valueArray = humanReadableValue.split(" "); 31 | double base = Double.parseDouble(valueArray[0]); 32 | String unit = valueArray[1]; 33 | if ("B".equals(unit)) { 34 | return base; 35 | } 36 | int exp = "KMGTPE".indexOf(unit.charAt(0)) + 1; 37 | return base * Math.pow(unitSize, exp); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 5557 3 | spring: 4 | main: 5 | allow-circular-references: true 6 | application: 7 | name: rocketmq-exporter 8 | http: 9 | encoding: 10 | charset: UTF-8 11 | enabled: true 12 | force: true 13 | logging: 14 | config: classpath:logback.xml 15 | 16 | rocketmq: 17 | config: 18 | webTelemetryPath: /metrics 19 | namesrvAddr: 127.0.0.1:9876 20 | rocketmqVersion: 4_9_4 21 | enableCollect: true 22 | enableACL: false # if >=4.4.0 23 | accessKey: # if >=4.4.0 24 | secretKey: # if >=4.4.0 25 | outOfTimeSeconds: 60 # Cache clear time with no update 26 | 27 | grpc: 28 | server: 29 | port: 5559 30 | 31 | threadpool: 32 | collect-client-metric-executor: 33 | core-pool-size: 10 34 | maximum-pool-size: 10 35 | keep-alive-time: 3000 36 | queueSize: 5000 37 | task: 38 | count: 5 # num of scheduled-tasks 39 | collectTopicOffset: 40 | cron: 15 0/1 * * * ? 41 | collectProducer: 42 | cron: 15 0/1 * * * ? 43 | collectConsumerOffset: 44 | cron: 15 0/1 * * * ? 45 | collectBrokerStatsTopic: 46 | cron: 15 0/1 * * * ? 47 | collectBrokerStats: 48 | cron: 15 0/1 * * * ? 49 | collectBrokerRuntimeStats: 50 | cron: 15 0/1 * * * ? 51 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | [%d{yyyy-MM-dd HH:mm:ss.SSS}] %5p %m%n 22 | 23 | 24 | 25 | 27 | ${user.home}/logs/exporterlogs/rocketmq-exporter.log 28 | true 29 | 30 | ${user.home}/logs/exporterlogs/rocketmq-exporter-%d{yyyy-MM-dd}.%i.log 31 | 50MB 32 | 1GB 33 | 3 34 | true 35 | 36 | 37 | [%d{yyyy-MM-dd HH:mm:ss.SSS}] %5p %m%n 38 | UTF-8 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/test/java/org/apache/rocketmq/exporter/util/UtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.rocketmq.exporter.util; 18 | 19 | import org.assertj.core.api.Assertions; 20 | import org.junit.Test; 21 | 22 | public class UtilsTest { 23 | 24 | @Test 25 | public void testMachineReadableByteCount() { 26 | double unitSize = 1024; 27 | Assertions.assertThat(Utils.machineReadableByteCount("100 B")).isEqualTo(100); 28 | Assertions.assertThat(Utils.machineReadableByteCount("1 KiB")).isEqualTo(Math.pow(unitSize, 1)); 29 | Assertions.assertThat(Utils.machineReadableByteCount("1 MiB")).isEqualTo(Math.pow(unitSize, 2)); 30 | Assertions.assertThat(Utils.machineReadableByteCount("1 GiB")).isEqualTo(Math.pow(unitSize, 3)); 31 | Assertions.assertThat(Utils.machineReadableByteCount("1 TiB")).isEqualTo(Math.pow(unitSize, 4)); 32 | Assertions.assertThat(Utils.machineReadableByteCount("1 PiB")).isEqualTo(Math.pow(unitSize, 5)); 33 | Assertions.assertThat(Utils.machineReadableByteCount("1 EiB")).isEqualTo(Math.pow(unitSize, 6)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /style/copyright/Apache.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 23 | -------------------------------------------------------------------------------- /style/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 31 | 32 | 35 | 36 | 39 | 40 | 43 | 44 | 47 | 48 | 51 | 52 | 55 | 56 | 59 | 60 | 63 | 64 | -------------------------------------------------------------------------------- /style/rmq_checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /style/rmq_codeStyle.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 33 | 39 | 46 | --------------------------------------------------------------------------------