Browse Source

新增代码

master
刘忱 1 year ago
commit
ed7b9c6d43
  1. 11
      .asf.yaml
  2. 1
      .gitignore
  3. 3
      .idea/.gitignore
  4. 18
      .idea/compiler.xml
  5. 7
      .idea/encodings.xml
  6. 25
      .idea/jarRepositories.xml
  7. 13
      .idea/misc.xml
  8. 124
      .idea/uiDesigner.xml
  9. 6
      .idea/vcs.xml
  10. 22
      .travis.yml
  11. 221
      DEPENDENCIES
  12. 549
      LICENSE
  13. 5
      NOTICE
  14. 70
      README.md
  15. 102
      docs/1_0_0/Milestone.md
  16. 152
      docs/1_0_0/UserGuide_CN.md
  17. 158
      docs/1_0_0/UserGuide_EN.md
  18. 374
      pom.xml
  19. 23
      src/main/docker/Dockerfile
  20. 36
      src/main/java/org/apache/rocketmq/dashboard/Application.java
  21. 57
      src/main/java/org/apache/rocketmq/dashboard/admin/MQAdminFactory.java
  22. 79
      src/main/java/org/apache/rocketmq/dashboard/admin/MQAdminPooledObjectFactory.java
  23. 47
      src/main/java/org/apache/rocketmq/dashboard/admin/MqAdminExtObjectPool.java
  24. 59
      src/main/java/org/apache/rocketmq/dashboard/aspect/admin/MQAdminAspect.java
  25. 30
      src/main/java/org/apache/rocketmq/dashboard/aspect/admin/annotation/OriginalControllerReturnValue.java
  26. 90
      src/main/java/org/apache/rocketmq/dashboard/config/AuthWebMVCConfigurerAdapter.java
  27. 161
      src/main/java/org/apache/rocketmq/dashboard/config/RMQConfigure.java
  28. 48
      src/main/java/org/apache/rocketmq/dashboard/controller/ClusterController.java
  29. 62
      src/main/java/org/apache/rocketmq/dashboard/controller/ConfigController.java
  30. 120
      src/main/java/org/apache/rocketmq/dashboard/controller/ConsumerController.java
  31. 60
      src/main/java/org/apache/rocketmq/dashboard/controller/DashboardController.java
  32. 95
      src/main/java/org/apache/rocketmq/dashboard/controller/LoginController.java
  33. 90
      src/main/java/org/apache/rocketmq/dashboard/controller/MessageController.java
  34. 71
      src/main/java/org/apache/rocketmq/dashboard/controller/MessageTraceController.java
  35. 64
      src/main/java/org/apache/rocketmq/dashboard/controller/MonitorController.java
  36. 41
      src/main/java/org/apache/rocketmq/dashboard/controller/NamesvrController.java
  37. 70
      src/main/java/org/apache/rocketmq/dashboard/controller/OpsController.java
  38. 45
      src/main/java/org/apache/rocketmq/dashboard/controller/ProducerController.java
  39. 101
      src/main/java/org/apache/rocketmq/dashboard/controller/TestController.java
  40. 120
      src/main/java/org/apache/rocketmq/dashboard/controller/TopicController.java
  41. 31
      src/main/java/org/apache/rocketmq/dashboard/exception/ServiceException.java
  42. 51
      src/main/java/org/apache/rocketmq/dashboard/filter/HttpBasicAuthorizedFilter.java
  43. 38
      src/main/java/org/apache/rocketmq/dashboard/interceptor/AuthInterceptor.java
  44. 53
      src/main/java/org/apache/rocketmq/dashboard/model/ConnectionInfo.java
  45. 61
      src/main/java/org/apache/rocketmq/dashboard/model/ConsumerGroupRollBackStat.java
  46. 46
      src/main/java/org/apache/rocketmq/dashboard/model/ConsumerMonitorConfig.java
  47. 94
      src/main/java/org/apache/rocketmq/dashboard/model/GroupConsumeInfo.java
  48. 39
      src/main/java/org/apache/rocketmq/dashboard/model/LoginInfo.java
  49. 36
      src/main/java/org/apache/rocketmq/dashboard/model/LoginResult.java
  50. 54
      src/main/java/org/apache/rocketmq/dashboard/model/MessagePage.java
  51. 55
      src/main/java/org/apache/rocketmq/dashboard/model/MessagePageTask.java
  52. 107
      src/main/java/org/apache/rocketmq/dashboard/model/MessageQueryByPage.java
  53. 237
      src/main/java/org/apache/rocketmq/dashboard/model/MessageTraceView.java
  54. 196
      src/main/java/org/apache/rocketmq/dashboard/model/MessageView.java
  55. 104
      src/main/java/org/apache/rocketmq/dashboard/model/QueueOffsetInfo.java
  56. 85
      src/main/java/org/apache/rocketmq/dashboard/model/QueueStatInfo.java
  57. 62
      src/main/java/org/apache/rocketmq/dashboard/model/TopicConsumerInfo.java
  58. 83
      src/main/java/org/apache/rocketmq/dashboard/model/User.java
  59. 67
      src/main/java/org/apache/rocketmq/dashboard/model/UserInfo.java
  60. 61
      src/main/java/org/apache/rocketmq/dashboard/model/request/ConsumerConfigInfo.java
  61. 40
      src/main/java/org/apache/rocketmq/dashboard/model/request/DeleteSubGroupRequest.java
  62. 82
      src/main/java/org/apache/rocketmq/dashboard/model/request/MessageQuery.java
  63. 58
      src/main/java/org/apache/rocketmq/dashboard/model/request/ResetOffsetRequest.java
  64. 28
      src/main/java/org/apache/rocketmq/dashboard/model/request/SendTopicMessageRequest.java
  65. 114
      src/main/java/org/apache/rocketmq/dashboard/model/request/TopicConfigInfo.java
  66. 31
      src/main/java/org/apache/rocketmq/dashboard/model/trace/MessageTraceGraph.java
  67. 32
      src/main/java/org/apache/rocketmq/dashboard/model/trace/MessageTraceStatusEnum.java
  68. 33
      src/main/java/org/apache/rocketmq/dashboard/model/trace/ProducerNode.java
  69. 27
      src/main/java/org/apache/rocketmq/dashboard/model/trace/SubscriptionNode.java
  70. 36
      src/main/java/org/apache/rocketmq/dashboard/model/trace/TraceNode.java
  71. 27
      src/main/java/org/apache/rocketmq/dashboard/permisssion/Permission.java
  72. 69
      src/main/java/org/apache/rocketmq/dashboard/permisssion/PermissionAspect.java
  73. 38
      src/main/java/org/apache/rocketmq/dashboard/permisssion/UserRoleEnum.java
  74. 49
      src/main/java/org/apache/rocketmq/dashboard/service/AbstractCommonService.java
  75. 27
      src/main/java/org/apache/rocketmq/dashboard/service/ClusterService.java
  76. 32
      src/main/java/org/apache/rocketmq/dashboard/service/ConfigService.java
  77. 58
      src/main/java/org/apache/rocketmq/dashboard/service/ConsumerService.java
  78. 36
      src/main/java/org/apache/rocketmq/dashboard/service/DashboardCollectService.java
  79. 42
      src/main/java/org/apache/rocketmq/dashboard/service/DashboardService.java
  80. 25
      src/main/java/org/apache/rocketmq/dashboard/service/LoginService.java
  81. 59
      src/main/java/org/apache/rocketmq/dashboard/service/MessageService.java
  82. 31
      src/main/java/org/apache/rocketmq/dashboard/service/MessageTraceService.java
  83. 30
      src/main/java/org/apache/rocketmq/dashboard/service/MonitorService.java
  84. 34
      src/main/java/org/apache/rocketmq/dashboard/service/OpsService.java
  85. 24
      src/main/java/org/apache/rocketmq/dashboard/service/PermissionService.java
  86. 24
      src/main/java/org/apache/rocketmq/dashboard/service/ProducerService.java
  87. 54
      src/main/java/org/apache/rocketmq/dashboard/service/TopicService.java
  88. 25
      src/main/java/org/apache/rocketmq/dashboard/service/UserService.java
  89. 23
      src/main/java/org/apache/rocketmq/dashboard/service/checker/CheckerType.java
  90. 24
      src/main/java/org/apache/rocketmq/dashboard/service/checker/RocketMqChecker.java
  91. 34
      src/main/java/org/apache/rocketmq/dashboard/service/checker/impl/ClusterHealthCheckerImpl.java
  92. 39
      src/main/java/org/apache/rocketmq/dashboard/service/checker/impl/TopicOnlyOneBrokerCheckerImpl.java
  93. 551
      src/main/java/org/apache/rocketmq/dashboard/service/client/MQAdminExtImpl.java
  94. 75
      src/main/java/org/apache/rocketmq/dashboard/service/client/MQAdminInstance.java
  95. 83
      src/main/java/org/apache/rocketmq/dashboard/service/impl/AbstractFileStore.java
  96. 76
      src/main/java/org/apache/rocketmq/dashboard/service/impl/ClusterServiceImpl.java
  97. 115
      src/main/java/org/apache/rocketmq/dashboard/service/impl/ConfigServiceImpl.java
  98. 332
      src/main/java/org/apache/rocketmq/dashboard/service/impl/ConsumerServiceImpl.java
  99. 157
      src/main/java/org/apache/rocketmq/dashboard/service/impl/DashboardCollectServiceImpl.java
  100. 73
      src/main/java/org/apache/rocketmq/dashboard/service/impl/DashboardServiceImpl.java

11
.asf.yaml

@ -0,0 +1,11 @@
github:
features:
# Enable issue management
issues: true
# Enable wiki
wiki: true
enabled_merge_buttons:
squash: true
merge: false
rebase: false

1
.gitignore

@ -0,0 +1 @@
/target

3
.idea/.gitignore

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

18
.idea/compiler.xml

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Annotation profile for rocketmq-dashboard" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.12/lombok-1.18.12.jar" />
</processorPath>
<module name="rocketmq-dashboard" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel target="8" />
</component>
</project>

7
.idea/encodings.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

25
.idea/jarRepositories.xml

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="apache.snapshots" />
<option name="name" value="Apache Snapshot Repository" />
<option name="url" value="https://repository.apache.org/snapshots" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

13
.idea/misc.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
<option name="workspaceImportForciblyTurnedOn" value="true" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
</project>

124
.idea/uiDesigner.xml

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

22
.travis.yml

@ -0,0 +1,22 @@
dist: trusty
notifications:
email:
recipients:
- dev@rocketmq.apache.org
on_success: change
on_failure: always
language: java
jdk:
- oraclejdk8
- oraclejdk11
script:
- travis_retry mvn -B clean apache-rat:check
- travis_retry mvn -B package findbugs:findbugs jacoco:report coveralls:report
# - travis_retry mvn -B package findbugs:findbugs coveralls:report
#after_success:
# - mvn sonar:sonar

221
DEPENDENCIES

@ -0,0 +1,221 @@
// ------------------------------------------------------------------
// Transitive dependencies of this project determined from the
// maven pom organized by organization.
// ------------------------------------------------------------------
rocketmq-dashboard
From: 'Alibaba Group' (https://github.com/alibaba)
- fastjson (https://github.com/alibaba/fastjson) com.alibaba:fastjson:jar:1.2.76
License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt)
From: 'an unknown organization'
- Code Generation Library (http://cglib.sourceforge.net/) cglib:cglib:jar:2.2.2
License: ASF 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- jcommander (http://jcommander.org) com.beust:jcommander:jar:1.72
License: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- FindBugs-jsr305 (http://findbugs.sourceforge.net/) com.google.code.findbugs:jsr305:jar:3.0.2
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- error-prone annotations (http://nexus.sonatype.org/oss-repository-hosting.html/error_prone_parent/error_prone_annotations) com.google.errorprone:error_prone_annotations:jar:2.3.4
License: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Guava InternalFutureFailureAccess and InternalFutures (https://github.com/google/guava/failureaccess) com.google.guava:failureaccess:bundle:1.0.1
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Guava: Google Core Libraries for Java (https://github.com/google/guava/guava) com.google.guava:guava:bundle:29.0-jre
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Guava ListenableFuture only (https://github.com/google/guava/listenablefuture) com.google.guava:listenablefuture:jar:9999.0-empty-to-avoid-conflict-with-guava
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- J2ObjC Annotations (https://github.com/google/j2objc/) com.google.j2objc:j2objc-annotations:jar:1.3
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- micrometer-core (https://github.com/micrometer-metrics/micrometer) io.micrometer:micrometer-core:jar:1.3.1
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- openmessaging-dledger (http://nexus.sonatype.org/oss-repository-hosting.html/dledger) io.openmessaging.storage:dledger:jar:0.2.2
- Bean Validation API (http://beanvalidation.org) jakarta.validation:jakarta.validation-api:jar:2.0.1
License: Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Java Native Access (https://github.com/java-native-access/jna) net.java.dev.jna:jna:jar:4.2.2
License: LGPL, version 2.1 (http://www.gnu.org/licenses/licenses.html) License: ASL, version 2 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- tomcat-embed-core (https://tomcat.apache.org/) org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.29
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- tomcat-embed-el (https://tomcat.apache.org/) org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.29
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- tomcat-embed-websocket (https://tomcat.apache.org/) org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.29
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- AspectJ runtime (https://www.eclipse.org/aspectj/) org.aspectj:aspectjrt:jar:1.9.6
License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html)
- AspectJ weaver (https://www.eclipse.org/aspectj/) org.aspectj:aspectjweaver:jar:1.9.6
License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html)
- Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (http://www.bouncycastle.org/java.html) org.bouncycastle:bcpkix-jdk15on:jar:1.68
License: Bouncy Castle Licence (http://www.bouncycastle.org/licence.html)
- Bouncy Castle Provider (http://www.bouncycastle.org/java.html) org.bouncycastle:bcprov-jdk15on:jar:1.68
License: Bouncy Castle Licence (http://www.bouncycastle.org/licence.html)
- Checker Qual (https://checkerframework.org) org.checkerframework:checker-qual:jar:2.11.1
License: The MIT License (http://opensource.org/licenses/MIT)
- HdrHistogram (http://hdrhistogram.github.io/HdrHistogram/) org.hdrhistogram:HdrHistogram:bundle:2.1.11
License: Public Domain, per Creative Commons CC0 (http://creativecommons.org/publicdomain/zero/1.0/) License: BSD-2-Clause (https://opensource.org/licenses/BSD-2-Clause)
- Hibernate Validator Engine (http://hibernate.org/validator/hibernate-validator) org.hibernate.validator:hibernate-validator:jar:6.0.18.Final
License: Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- jOOR (https://github.com/jOOQ/jOOR) org.jooq:joor:bundle:0.9.6
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- LatencyUtils (http://latencyutils.github.io/LatencyUtils/) org.latencyutils:LatencyUtils:jar:2.0.3
License: Public Domain, per Creative Commons CC0 (http://creativecommons.org/publicdomain/zero/1.0/)
- Project Lombok (https://projectlombok.org) org.projectlombok:lombok:jar:1.18.12
License: The MIT License (https://projectlombok.org/LICENSE)
- SnakeYAML (http://www.snakeyaml.org) org.yaml:snakeyaml:bundle:1.19
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
From: 'Apache Software Foundation' (http://www.apache.org)
- rocketmq-acl 4.9.0 (http://rocketmq.apache.org/rocketmq-acl/) org.apache.rocketmq:rocketmq-acl:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-broker 4.9.0 (http://rocketmq.apache.org/rocketmq-broker/) org.apache.rocketmq:rocketmq-broker:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-client 4.9.0 (http://rocketmq.apache.org/rocketmq-client/) org.apache.rocketmq:rocketmq-client:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-common 4.9.0 (http://rocketmq.apache.org/rocketmq-common/) org.apache.rocketmq:rocketmq-common:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-filter 4.9.0 (http://rocketmq.apache.org/rocketmq-filter/) org.apache.rocketmq:rocketmq-filter:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-logging 4.9.0 (http://rocketmq.apache.org/rocketmq-logging/) org.apache.rocketmq:rocketmq-logging:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-namesrv 4.9.0 (http://rocketmq.apache.org/rocketmq-namesrv/) org.apache.rocketmq:rocketmq-namesrv:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-remoting 4.9.0 (http://rocketmq.apache.org/rocketmq-remoting/) org.apache.rocketmq:rocketmq-remoting:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-srvutil 4.9.0 (http://rocketmq.apache.org/rocketmq-srvutil/) org.apache.rocketmq:rocketmq-srvutil:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-store 4.9.0 (http://rocketmq.apache.org/rocketmq-store/) org.apache.rocketmq:rocketmq-store:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- rocketmq-tools 4.9.0 (http://rocketmq.apache.org/rocketmq-tools/) org.apache.rocketmq:rocketmq-tools:jar:4.9.0
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
From: 'Eclipse Foundation' (https://www.eclipse.org)
- Jakarta Annotations API (https://projects.eclipse.org/projects/ee4j.ca) jakarta.annotation:jakarta.annotation-api:jar:1.3.5
License: EPL 2.0 (http://www.eclipse.org/legal/epl-2.0) License: GPL2 w/ CPE (https://www.gnu.org/software/classpath/license.html)
From: 'FasterXML' (http://fasterxml.com/)
- Jackson-annotations (http://github.com/FasterXML/jackson) com.fasterxml.jackson.core:jackson-annotations:bundle:2.10.1
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Jackson-core (https://github.com/FasterXML/jackson-core) com.fasterxml.jackson.core:jackson-core:bundle:2.10.1
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- jackson-databind (http://github.com/FasterXML/jackson) com.fasterxml.jackson.core:jackson-databind:bundle:2.10.1
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Jackson datatype: jdk8 (https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8) com.fasterxml.jackson.datatype:jackson-datatype-jdk8:bundle:2.10.1
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Jackson datatype: JSR310 (https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310) com.fasterxml.jackson.datatype:jackson-datatype-jsr310:bundle:2.10.1
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Jackson-module-parameter-names (https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names) com.fasterxml.jackson.module:jackson-module-parameter-names:bundle:2.10.1
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
From: 'fasterxml.com' (http://fasterxml.com)
- ClassMate (http://github.com/FasterXML/java-classmate) com.fasterxml:classmate:bundle:1.3.4
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
From: 'JBoss by Red Hat' (http://www.jboss.org)
- JBoss Logging 3 (http://www.jboss.org) org.jboss.logging:jboss-logging:jar:3.3.2.Final
License: Apache License, version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
From: 'ObjectWeb' (http://www.objectweb.org/)
- ASM Core (http://asm.objectweb.org/asm/) asm:asm:jar:3.3.1
License: BSD (http://asm.objectweb.org/license.html)
From: 'Oracle' (http://www.oracle.com)
- JavaBeans Activation Framework API jar (http://java.net/all/javax.activation-api/) javax.activation:javax.activation-api:jar:1.2.0
License: CDDL/GPLv2+CE (https://github.com/javaee/activation/blob/master/LICENSE.txt)
From: 'Oracle Corporation' (http://www.oracle.com/)
- jaxb-api (https://github.com/javaee/jaxb-spec/jaxb-api) javax.xml.bind:jaxb-api:jar:2.3.1
License: CDDL 1.1 (https://oss.oracle.com/licenses/CDDL+GPL-1.1) License: GPL2 w/ CPE (https://oss.oracle.com/licenses/CDDL+GPL-1.1)
From: 'Pivotal Software, Inc.' (https://spring.io)
- Spring Boot (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot) org.springframework.boot:spring-boot:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot Actuator (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-actuator) org.springframework.boot:spring-boot-actuator:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot Actuator AutoConfigure (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-actuator-autoconfigure) org.springframework.boot:spring-boot-actuator-autoconfigure:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot AutoConfigure (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-autoconfigure) org.springframework.boot:spring-boot-autoconfigure:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot Starter (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter) org.springframework.boot:spring-boot-starter:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot Actuator Starter (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-actuator) org.springframework.boot:spring-boot-starter-actuator:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot Json Starter (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-json) org.springframework.boot:spring-boot-starter-json:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot Logging Starter (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-logging) org.springframework.boot:spring-boot-starter-logging:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot Tomcat Starter (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-tomcat) org.springframework.boot:spring-boot-starter-tomcat:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot Validation Starter (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-validation) org.springframework.boot:spring-boot-starter-validation:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Boot Web Starter (https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-web) org.springframework.boot:spring-boot-starter-web:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
From: 'Pivotal Software, Inc.' (https://www.spring.io)
- Spring Data Core (https://www.spring.io/spring-data/spring-data-commons) org.springframework.data:spring-data-commons:jar:2.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
From: 'QOS.ch' (http://www.qos.ch)
- Logback Classic Module (http://logback.qos.ch/logback-classic) ch.qos.logback:logback-classic:jar:1.2.3
License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)
- Logback Core Module (http://logback.qos.ch/logback-core) ch.qos.logback:logback-core:jar:1.2.3
License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)
- JUL to SLF4J bridge (http://www.slf4j.org) org.slf4j:jul-to-slf4j:jar:1.7.29
License: MIT License (http://www.opensource.org/licenses/mit-license.php)
- SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.26
License: MIT License (http://www.opensource.org/licenses/mit-license.php)
From: 'Shigeru Chiba, www.javassist.org'
- Javassist (http://www.javassist.org/) org.javassist:javassist:bundle:3.20.0-GA
License: MPL 1.1 (http://www.mozilla.org/MPL/MPL-1.1.html) License: LGPL 2.1 (http://www.gnu.org/licenses/lgpl-2.1.html) License: Apache License 2.0 (http://www.apache.org/licenses/)
From: 'Spring IO' (https://spring.io/projects/spring-framework)
- Spring AOP (https://github.com/spring-projects/spring-framework) org.springframework:spring-aop:jar:5.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Beans (https://github.com/spring-projects/spring-framework) org.springframework:spring-beans:jar:5.2.1.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Context (https://github.com/spring-projects/spring-framework) org.springframework:spring-context:jar:5.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Core (https://github.com/spring-projects/spring-framework) org.springframework:spring-core:jar:5.2.1.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Expression Language (SpEL) (https://github.com/spring-projects/spring-framework) org.springframework:spring-expression:jar:5.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Commons Logging Bridge (https://github.com/spring-projects/spring-framework) org.springframework:spring-jcl:jar:5.2.1.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Web (https://github.com/spring-projects/spring-framework) org.springframework:spring-web:jar:5.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
- Spring Web MVC (https://github.com/spring-projects/spring-framework) org.springframework:spring-webmvc:jar:5.2.2.RELEASE
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
From: 'The Apache Software Foundation' (http://www.apache.org/)
- Commons CLI (http://commons.apache.org/cli/) commons-cli:commons-cli:jar:1.2
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.9
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Commons Collections (http://commons.apache.org/collections/) commons-collections:commons-collections:jar:3.2.2
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Commons Digester (http://commons.apache.org/digester/) commons-digester:commons-digester:jar:2.1
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Commons Lang (http://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.4
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
From: 'The Apache Software Foundation' (https://www.apache.org/)
- Apache Commons BeanUtils (https://commons.apache.org/proper/commons-beanutils/) commons-beanutils:commons-beanutils:jar:1.9.4
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Commons Validator (http://commons.apache.org/proper/commons-validator/) commons-validator:commons-validator:jar:1.7
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Commons Pool (http://commons.apache.org/proper/commons-pool/) org.apache.commons:commons-pool2:jar:2.4.3
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Log4j API (https://logging.apache.org/log4j/2.x/log4j-api/) org.apache.logging.log4j:log4j-api:jar:2.12.1
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Log4j to SLF4J Adapter (https://logging.apache.org/log4j/2.x/log4j-to-slf4j/) org.apache.logging.log4j:log4j-to-slf4j:jar:2.12.1
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt)
From: 'The Netty Project' (http://netty.io/)
- Netty/All-in-One (http://netty.io/netty-all/) io.netty:netty-all:jar:4.0.42.Final
License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)

549
LICENSE

@ -0,0 +1,549 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (properties) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-----------------------------------------------------------------------------
rocket-console
-------------------------------------------
develop base on didapinche's rocket-console
https://github.com/didapinchegit/rocket-console
Apache License
Version 2.0, January 2004
angular
-------------------------------------------
https://github.com/angular/angular
The MIT License
Copyright (c) 2014-2017 Google, Inc. http://angular.io
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
angular-material
-----------------------------------------
https://github.com/angular/material
The MIT License
Copyright (c) 2014-2017 Google, Inc. http://angularjs.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
bootstrap
-------------------------------------------
http://getbootstrap.com/
The MIT License (MIT)
Copyright (c) 2011-2017 Twitter, Inc.
Copyright (c) 2011-2017 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
bootstrap-material-design
-------------------------------------------------
The MIT License (MIT)
Copyright (c) 2015-2016, Federico Zivolo and contributors - https://github.com/FezVrasta/bootstrap-material-design
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Acknowledgements:
Some original Bootstrap code and documentation http://getbootstrap.com Copyright (c) 2011-2015 Twitter, Inc
Some original MDL code http://www.getmdl.io/ Copyright 2015 Google Inc. All Rights Reserved.
angular-chosen
--------------------------------------
The MIT License
Copyright (c) 2013 Localytics http://www.localytics.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
bootstrap-datetimepicker
----------------------------------------------------------
https://github.com/Eonasdan/bootstrap-datetimepicker
The MIT License (MIT)
Copyright (c) 2015 Jonathan Peterson (@Eonasdan)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
echarts
----------------------------------
https://github.com/apache/echarts
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
html5-boilerplate
------------------------------------------
https://github.com/h5bp/html5-boilerplate
h5bp/html5-boilerplate is licensed under the MIT License
Copyright (c) HTML5 Boilerplate
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
jquery
---------------------
Copyright JS Foundation and other contributors, https://js.foundation/
This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/jquery/jquery
The following license applies to all parts of this software except as
documented below:
====
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
====
All files located in the node_modules and external directories are
externally maintained libraries used by this software which have their
own licenses; we recommend you read them, as their terms may differ from
the terms above.
12.json-bigint
https://github.com/sidorares/json-bigint
The MIT License (MIT)
Copyright (c) 2013 Andrey Sidorov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Ladda
---------------
https://github.com/hakimel/Ladda
Copyright (C) 2016 Hakim El Hattab, http://hakim.se
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
ngDialog
------------
http://github.com/likeastore/ngDialog
MIT Licensed
Copyright (c) 2013-2015, Likeastore.com info@likeastore.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
notification
---------------------
https://github.com/alexcrack/angular-ui-notification
The MIT License (MIT)
Copyright (c) 2014 Alexey Avramchik
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
pagination
---------------------
https://github.com/317482454/tm.pagination
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
bootstrap-validator
---------------------------
https://github.com/1000hz/bootstrap-validator
The MIT License (MIT)
Copyright (c) 2016 Cina Saffary
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

5
NOTICE

@ -0,0 +1,5 @@
Apache RocketMQ
Copyright 2016-2021 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).

70
README.md

@ -0,0 +1,70 @@
## RocketMQ Dashboard [![Build Status](https://api.travis-ci.com/apache/rocketmq-dashboard.svg?branch=master)](https://travis-ci.com/github/apache/rocketmq-dashboard) [![Coverage Status](https://coveralls.io/repos/github/apache/rocketmq-dashboard/badge.svg?branch=master)](https://coveralls.io/github/apache/rocketmq-dashboard?branch=master)
[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/apache/rocketmq-dashboard.svg)](http://isitmaintained.com/project/apache/rocketmq-dashboard "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/apache/rocketmq-dashboard.svg)](http://isitmaintained.com/project/apache/rocketmq-dashboard "Percentage of issues still open")
[![Twitter Follow](https://img.shields.io/twitter/follow/ApacheRocketMQ?style=social)](https://twitter.com/intent/follow?screen_name=ApacheRocketMQ)
## How To Install
### With Docker
* get docker image
```
mvn clean package -Dmaven.test.skip=true docker:build
```
or
```
docker pull apacherocketmq/rocketmq-console:2.0.0
```
> currently the newest available docker image is apacherocketmq/rocketmq-console:2.0.0
* run it (change namesvrAddr and port yourself)
```
docker run -e "JAVA_OPTS=-Drocketmq.namesrv.addr=127.0.0.1:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" -p 8080:8080 -t apacherocketmq/rocketmq-console:2.0.0
```
### Without Docker
require java 1.8+
```
mvn spring-boot:run
```
or
```
mvn clean package -Dmaven.test.skip=true
java -jar target/rocketmq-dashboard-1.0.1-SNAPSHOT.jar
```
#### Tips
* if you download package slow,you can change maven's mirror(maven's settings.xml)
```
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
```
* if you use the rocketmq < 3.5.8,please add -Dcom.rocketmq.sendMessageWithVIPChannel=false when you start rocketmq-dashboard(or you can change it in ops page)
* change the rocketmq.config.namesrvAddr in resource/application.properties.(or you can change it in ops page)
## UserGuide
[English](https://github.com/apache/rocketmq-dashboard/blob/master/docs/1_0_0/UserGuide_EN.md)
[中文](https://github.com/apache/rocketmq-dashboard/blob/master/docs/1_0_0/UserGuide_CN.md)
## Contributing
We are always very happy to have contributions, whether for trivial cleanups or big new features. Please see the RocketMQ main website to read [details](http://rocketmq.apache.org/docs/how-to-contribute/).
## License
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) Copyright (C) Apache Software Foundation

102
docs/1_0_0/Milestone.md

@ -0,0 +1,102 @@
#Deploy Plan
we will deploy the first rocketmq-console-ng use rocketmq-tools 3.5.8(or 4.0.0),base on [rocket-console](https://github.com/didapinchegit/rocket-console),thanks didapinche.com
## Framework
* 0. we use spring-boot + bootstrap + angularjs
## something to improve
* 0. clean code (checkStyle codeStyle to be done)
* 1. international
* 2. compress fe'resource
* 3. navigation bar can improve
* 4. write operation need confirm,action show the detail result
* 5. layout/UI should improve
* 6. change to spring-boot
## something to fix
* query Message by topic and time is not accurate, will lost some message
* consumer can consume the message when topic has been deleted
* can't show producerList,we can only query a online producer use topic and groupName,not easy to use.
* resetOffset should be improve,online consumer can return the reset result but offline's can't
* we can't set clusterName when create topic or consumer
* when create a new consumer,if not be consumed,can't be found in consumerList
## something to add
* 1. dashboard
# Roadmap
## Improve
- [x] clean code (checkStyle codeStyle to be done) -- StyleTang
- [x] international -- Deploy by [tcrow](https://github.com/tcrow)
- [x] layout/UI -- Deploy by [tcrow](https://github.com/tcrow)
- [x] compress fe'resource
- [x] navigation bar can improve
- [x] write operation need confirm,action show the detail result || already have
- [x] layout/UI should improve
- [x] change to spring-boot -- Deploy by syzjava
- [x] change to bootstrap angularjs -- Deploy by [tcrow](https://github.com/tcrow)
- [x] improve search message --StyleTang
## Fix
- [x] query Message by topic and time is not accurate, will lost some message -- StyleTang (need test)
- [x] consumer can consume the message when topic has been deleted // offset be clear.if have problem,reopen it.
- [ ] can't show producerList,we can only query a online producer use topic and groupName,not easy to use. [need this issues](https://issues.apache.org/jira/browse/ROCKETMQ-49)(next milestone)
- [ ] resetOffset should be improve,online consumer can return the reset result but offline's can't //this version(3.5.8) may be can't fix (next milestone)
- [x] we can't set clusterName when create topic or consumer -- StyleTang
- [x] when create a new consumer,if not be consumed,can't be found in consumerList //it Fixed,But this page is too slow,need improve --StyleTang
- [x] message view page,resend message (version >=3.5.8) have bug -- StyleTang
## Add
- [ ] DashboardController -- Deploy by [tcrow](https://github.com/tcrow)
- [x] rocketmq topic tps 5m line chart
- [x] rocketmq topic top10 table
- [x] broker load 5m line chart
- [x] broker load top10 table
- [ ] topic exception table(next milestone)
## Already Have (Deploy by StyleTang) But Can Improve
### Cluster
- [x] ClusterController
- [x] Cluster OverView
- [x] Broker Status
- [x] Broker Config
### Topic
- [x] TopicController
- [x] TopicList
- [x] Topic Status
- [x] Topic Router
- [x] View Topic Config
- [x] Topci Add / Update
- [X] Send A Test Topic
- [x] Reset ConsumerGroup's Offset Under This Topic
- [x] Delete This Topic
### Producer
- [x] ProducerController
- [x] Producer Client Info
### Consumer
- [x] ConsumerController
- [x] ConsumerList
- [x] Consumer Client Info
- [x] Topic Consume Status Under This Consumer Group
- [x] View Consumer Config
- [x] Consumer Add / Update
- [x] Delete This Consumer
### Message
- [x] MessageController
- [x] Query By Topic And Time
- [x] Query By Topic And Key
- [x] Query By MessageId(OffsetMessageId)
- [x] A Nice Message Detail View
- [x] Message Consume Status
- [x] Resend Message To A Consume Group

152
docs/1_0_0/UserGuide_CN.md

@ -0,0 +1,152 @@
# RocketMQ使用文档
## 运维页面
* 你可以修改这个服务使用的namesrv的地址
* 你可以修改这个服务是否使用VIPChannel(如果你的mq server版本小于3.5.8,请设置不使用)
## 驾驶舱
* 查看broker的消息量(总量/5分钟图)
* 查看单一主题的消息量(总量/趋势图)
## 集群页面
* 查看集群的分布情况
* cluster与broker关系
* broker
* 查看broker具体信息/运行信息
* 查看broker配置信息
## 主题页面
* 展示所有的主题,可以通过搜索框进行过滤
* 筛选 普通/重试/死信 主题
* 添加/更新主题
* clusterName 创建在哪几个cluster上
* brokerName 创建在哪几个broker上
* topicName 主题名
* writeQueueNums 写队列数量
* readQueueNums 读队列数量
* perm //2是写 4是读 6是读写
* 状态 查询消息投递状态(投递到哪些broker/哪些queue/多少量等)
* 路由 查看消息的路由(现在你发这个主题的消息会发往哪些broker,对应broker的queue信息)
* CONSUMER管理(这个topic都被哪些group消费了,消费情况何如)
* topic配置(查看变更当前的配置)
* 发送消息(向这个主题发送一个测试消息)
* 重置消费位点(分为在线和不在线两种情况,不过都需要检查重置是否成功)
* 删除主题 (会删除掉所有broker以及namesrv上的主题配置和路由信息)
## 消费者页面
* 展示所有的消费组,可以通过搜索框进行过滤
* 刷新页面/每隔五秒定时刷新页面
* 按照订阅组/数量/TPS/延迟 进行排序
* 添加/更新消费组
* clusterName 创建在哪几个集群上
* brokerName 创建在哪几个broker上
* groupName 消费组名字
* consumeEnable //是否可以消费 FALSE的话将无法进行消费
* consumeBroadcastEnable //是否可以广播消费
* retryQueueNums //重试队列的大小
* brokerId //正常情况从哪消费
* whichBrokerWhenConsumeSlowly//出问题了从哪消费
* 终端 在线的消费客户端查看,包括版本订阅信息和消费模式
* 消费详情 对应消费组的消费明细查看,这个消费组订阅的所有Topic的消费情况,每个queue对应的消费client查看(包括Retry消息)
* 配置 查看变更消费组的配置
* 删除 在指定的broker上删除消费组
## 发布管理页面
* 通过Topic和Group查询在线的消息生产者客户端
* 信息包含客户端主机 版本
## 消息查询页面
* 根据Topic和时间区间查询
*由于数据量大 最多只会展示2000条,多的会被忽略
* 根据Topic和Key进行查询
* 最多只会展示64条
* 根据消息主题和消息Id进行消息的查询
* 消息详情可以展示这条消息的详细信息,查看消息对应到具体消费组的消费情况(如果异常,可以查看具体的异常信息)。可以向指定的消费组重发消息。
## HTTPS 方式访问Dashboard
* HTTPS功能实际上是使用SpringBoot提供的配置功能即可完成,首先,需要有一个SSL KeyStore来存放服务端证书,可以使用本工程所提供的测试密钥库:
resources/rmqcngkeystore.jks, 它可以通过如下keytool命令生成
```
#生成库并以rmqcngKey别名添加秘钥
keytool -genkeypair -alias rmqcngKey -keyalg RSA -validity 3650 -keystore rmqcngkeystore.jks
#查看keystore内容
keytool -list -v -keystore rmqcngkeystore.jks
#转换库格式
keytool -importkeystore -srckeystore rmqcngkeystore.jks -destkeystore rmqcngkeystore.jks -deststoretype pkcs12
```
* 配置resources/application.properties, 打开SSL的相关选项, 启动dashboard后即开启了HTTPS.
```
#设置https端口
server.port=8443
### SSL setting
#server.ssl.key-store=classpath:rmqcngkeystore.jks
#server.ssl.key-store-password=rocketmq
#server.ssl.keyStoreType=PKCS12
#server.ssl.keyAlias=rmqcngkey
```
## 登录访问Dashboard
在访问Dashboard时支持按用户名和密码登录控制台,在操作完成后登出。需要做如下的设置:
* 1.在Spring配置文件resources/application.properties中修改rocketmq.config.loginRequired=true开启登录功能
```$xslt
# 开启登录功能
rocketmq.config.loginRequired=true
# Dashboard文件目录,登录用户配置文件所在目录
rocketmq.config.dataPath=/tmp/rocketmq-console/data
```
* 2.确保${rocketmq.config.dataPath}定义的目录存在,并且该目录下创建登录配置文件"users.properties", 如果该目录下不存在此文件,则默认使用resources/users.properties文件。
users.properties文件格式为:
```$xslt
# 该文件支持热修改,即添加和修改用户时,不需要重新启动console
# 格式, 每行定义一个用户, username=password[,N] #N是可选项,可以为0 (普通用户); 1 (管理员)
#定义管理员
admin=admin,1
#定义普通用户
user1=user1
user2=user2
```
* 3.启动控制台则开启了登录功能
## 权限检验
如果用户访问console时开启了登录功能,会按照登录的角色对访问的接口进行权限控制。
* 1.在Spring配置文件resources/application.properties中修改rocketmq.config.loginRequired=true开启登录功能
```$xslt
# 开启登录功能
rocketmq.config.loginRequired=true
# Dashboard文件目录,登录用户配置文件所在目录
rocketmq.config.dataPath=/tmp/rocketmq-console/data
```
* 2.确保${rocketmq.config.dataPath}定义的目录存在,并且该目录下创建访问权限配置文件"role-permission.yml",
如果该目录下不存在此文件,则默认使用resources/role-permission.yml文件。该文件保存了普通用户角色所有能访问的接口地址。
role-permission.yml文件格式为:
```$xslt
# 该文件支持热修改,即添加和修改用户时,不需要重新启动console
# 格式,如果增加和删除接口权限,直接在列表中增加和删除接口地址即可。
# 接口路径配置支持通配符
# * 表示匹配0或多个不是/的字符
# ** 表示匹配0或多个任意字符
# ? 表示匹配1个任意字符
rolePerms:
# 普通用户
ordinary:
- /rocketmq/nsaddr
- /ops/*
- /dashboard/**
- /topic/*.query
- /topic/sendTopicMessage.do
- /producer/*.query
- /message/*
- /messageTrace/*
- /monitor/*
....
```
* 3.前端页面显示上,为了更好区分普通用户和admin用户权限,关于资源的删除、更新等操作按钮不对普通用户角色显示,如果要执行资源相关操作,需要退出使用admin角色登录。

158
docs/1_0_0/UserGuide_EN.md

@ -0,0 +1,158 @@
# RocketMQ User Guide
## OPS Page
* You can change dashboard's namesrvAddr here
* You can change the value of useVIPChannel here (if you rocketMQ version < 3.5.8,the value of useVIPChannel should be false)
## DashBoard Page
* broker's message count (broker total message count/5 min trend)
* topic's message count(topic total message count/5 min trend)
## Cluster Page
* Cluster Detail
* relation between cluster and broker
* broker's master / salve node
* broker'a detail info(runtime info)
* broker's config
## Topic Page
* show all the topics,you can filter topic by search bar
* filter (Normal/retry/dead) topic
* Add/Update Topic
* clusterName (create on which cluster)
* brokerName (create on which broker)
* topicName
* writeQueueNums
* readQueueNums
* perm //2 for write 4 for read 6 for write and read
* STATUS look over message send status(send to which broker/which queue/how many messages)
* ROUTER look update topic's router(this topic send to which broker,the broker's queue info)
* CONSUMER MANAGE(this topic consume by which group,how about the consume state)
* TOPIC CONFIG(check or change the topic's config)
* SEND MESSAGE(send a test message)
* Reset CONSUMER OFFSET (the consumer online or not online is different,you need check the reset result)
* DELETE (will delete the topic on all broker and namesrv)
## Consumer Page
* show all the consumers,you can filter consumer by search bar
* refresh page/refresh page per 5 seconds
* order by SubscriptionGroup/Quantity/TPS/Delay
* Add/Update Consumer
* clusterName (create on which cluster)
* brokerName (create on which broker)
* groupName (consumer group name)
* consumeEnable (this group can't consume message if this is false)
* consumeBroadcastEnable (can't use broadcast is this is false)
* retryQueueNums
* brokerId (consume form where when broker is normal)
* whichBrokerWhenConsumeSlowly(consume form where when broker has problem)
* CLIENT (look over online consumer's client,include subscribe info and consume mode)
* CONSUME DETAIL (look over this consumer's consume detail,broker offset and the consumer offset,queue consumed by which client)
* CONFIG (check or change the consumer's config)
* DELETE (delete the consumer group on selected group)
## Producer Page
* Query online producer client by topic and group
* show client's server / version
## Message Page
* Query By Topic And Time
*Only Return 2000 Messages,the message more than 2000 will be hide
* Query By Topic And Key
* Only Return 64 Messages
* Query By Topic And MessageId
* look over this message's detail info.you can see the message's consume state(each group has one line),show the exception message if has exception.
you can send this message to the group you selected
## Access Dashboard with HTTPS
* SpringBoot itself has provided the SSL configuration. You can use the project test Keystore:resources/rmqcngkeystore.jks. The store is generated with the following unix keytool commands:
```
#Generate Keystore and add alias rmqcngKey
keytool -genkeypair -alias rmqcngKey -keyalg RSA -validity 3650 -keystore rmqcngkeystore.jks
#View keystore content
keytool -list -v -keystore rmqcngkeystore.jks
#Transfer type as official
keytool -importkeystore -srckeystore rmqcngkeystore.jks -destkeystore rmqcngkeystore.jks -deststoretype pkcs12
```
* Uncomment the following SSL properties in resources/application.properties. restart Dashboard then access with HTTPS.
```
#Set https port
server.port=8443
### SSL setting
server.ssl.key-store=classpath:rmqcngkeystore.jks
server.ssl.key-store-password=rocketmq
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias=rmqcngkey
```
## Login/Logout on Dashboard
Access Dashboard with username and password and logout to leave the dashboard。To stage the function on, we need the steps below:
* 1.Turn on the property in resources/application.properties.
```$xslt
# open the login func
rocketmq.config.loginRequired=true
# Directory of ashboard & login user configure file
rocketmq.config.dataPath=/tmp/rocketmq-console/data
```
* 2.Make sure the directory defined in property ${rocketmq.config.dataPath} exists and the file "users.properties" is created under it.
The dashboard system will use the resources/users.properties by default if a customized file is not found。
The format in the content of users.properties:
```$xslt
# This file supports hot change, any change will be auto-reloaded without Console restarting.
# Format: a user per line, username=password[,N] #N is optional, 0 (Normal User); 1 (Admin)
# Define Admin
admin=admin,1
# Define Normal users
user1=user1
user2=user2
```
* 3.Restart Console Application after above configuration setting well.
## Permission Control
If the login function is enabled when a user accesses the Console, the user controls the access permission of the interface based on the login role.
* 1.Turn on the property in resources/application.properties.
```$xslt
# open the login func
rocketmq.config.loginRequired=true
# Directory of ashboard & login user configure file
rocketmq.config.dataPath=/tmp/rocketmq-console/data
```
* 2.Make sure the directory defined in property ${rocketmq.config.dataPath} exists and the permission control file "role-permission.yml" is created under it.
The console system will use the resources/role-permission.yml by default if a customized file is not found。
The format in the content of role-permission.yml:
```$xslt
# This file supports hot change, any change will be auto-reloaded without Console restarting.
# Format: To add or delete interface permissions, add or delete interface addresses from the list.
# the interface paths can be configured with wildcard characters.
# ?: Matches 1 characters.
# *: Matches 0 or more characters that are not /.
# **: Matches 0 or more characters.
rolePerms:
# ordinary user
ordinary:
- /rocketmq/nsaddr
- /ops/*
- /dashboard/**
- /topic/*.query
- /topic/sendTopicMessage.do
- /producer/*.query
- /message/*
- /messageTrace/*
- /monitor/*
....
```
* 3.On the front page, operation buttons such as deleting and updating resources are not displayed for common users in order to better distinguish the rights of common users and admin users. If need to operate related resources, log out and use the admin role to log in

374
pom.xml

@ -0,0 +1,374 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>18</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-dashboard</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<name>rocketmq-dashboard</name>
<scm>
<url>git@github.com:apache/rocketmq-dashboard.git</url>
<connection>scm:git:git@github.com:apache/rocketmq-dashboard.git</connection>
<developerConnection>scm:git:git@github.com:apache/rocketmq-dashboard.git</developerConnection>
<tag>rocketmq-dashboard-1.0.0</tag>
</scm>
<mailingLists>
<mailingList>
<name>Development List</name>
<subscribe>dev-subscribe@rocketmq.apache.org</subscribe>
<unsubscribe>dev-unsubscribe@rocketmq.apache.org</unsubscribe>
<post>dev@rocketmq.apache.org</post>
</mailingList>
<mailingList>
<name>User List</name>
<subscribe>users-subscribe@rocketmq.apache.org</subscribe>
<unsubscribe>users-unsubscribe@rocketmq.apache.org</unsubscribe>
<post>users@rocketmq.apache.org</post>
</mailingList>
<mailingList>
<name>Commits List</name>
<subscribe>commits-subscribe@rocketmq.apache.org</subscribe>
<unsubscribe>commits-unsubscribe@rocketmq.apache.org</unsubscribe>
<post>commits@rocketmq.apache.org</post>
</mailingList>
</mailingLists>
<developers>
<developer>
<id>Apache RocketMQ</id>
<name>Apache RocketMQ of ASF</name>
<url>https://rocketmq.apache.org/</url>
</developer>
</developers>
<organization>
<name>Apache Software Foundation</name>
<url>http://www.apache.org</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
<distribution>repo</distribution>
</license>
</licenses>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<guava.version>29.0-jre</guava.version>
<commons-digester.version>2.1</commons-digester.version>
<commons-lang.version>2.6</commons-lang.version>
<commons-io.version>2.4</commons-io.version>
<commons-cli.version>1.2</commons-cli.version>
<rocketmq.version>4.9.0</rocketmq.version>
<surefire.version>2.19.1</surefire.version>
<aspectj.version>1.9.6</aspectj.version>
<lombok.version>1.18.12</lombok.version>
<main.basedir>${basedir}/../..</main.basedir>
<docker.image.prefix>apacherocketmq</docker.image.prefix>
<spring.boot.version>2.2.2.RELEASE</spring.boot.version>
<mockito-inline.version>3.3.3</mockito-inline.version>
<jaxb-api.version>2.3.1</jaxb-api.version>
<commons-pool2.version>2.4.3</commons-pool2.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-tools</artifactId>
<version>${rocketmq.version}</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-namesrv</artifactId>
<version>${rocketmq.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-broker</artifactId>
<version>${rocketmq.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- Spring AOP + AspectJ -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>joor</artifactId>
<version>0.9.6</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.68</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb-api.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${mockito-inline.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>${commons-pool2.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.82.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<compilerVersion>${maven.compiler.source}</compilerVersion>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Use dockerfile-maven instead, https://github.com/spotify/dockerfile-maven -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.11</version>
<dependencies>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>javax.activation-api</artifactId>
<version>1.2.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<imageTags>
<imageTag>${project.version}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.17</version>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<configuration>
<excludes>src/main/resources</excludes>
<configLocation>style/rmq_checkstyle.xml</configLocation>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.4</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>4.3.0</version>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb-api.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
<version>0.12</version>
<configuration>
<excludes>
<exclude>.gitignore</exclude>
<exclude>.travis.yml</exclude>
<exclude>.asf.yaml</exclude>
<exclude>README.md</exclude>
<exclude>.github/**</exclude>
<exclude>docs/**</exclude>
<exclude>src/main/resources/static/vendor/**</exclude>
<exclude>src/main/resources/static/src/data/**</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

23
src/main/docker/Dockerfile

@ -0,0 +1,23 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
FROM java:8
VOLUME /tmp
ADD rocketmq-dashboard-*.jar rocketmq-dashboard.jar
RUN sh -c 'touch /rocketmq-dashboard.jar'
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -jar /rocketmq-dashboard.jar" ]

36
src/main/java/org/apache/rocketmq/dashboard/Application.java

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.jmx.support.RegistrationPolicy;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@ServletComponentScan
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

57
src/main/java/org/apache/rocketmq/dashboard/admin/MQAdminFactory.java

@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.admin;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
import org.apache.rocketmq.tools.admin.MQAdminExt;
@Slf4j
public class MQAdminFactory {
private RMQConfigure rmqConfigure;
public MQAdminFactory(RMQConfigure rmqConfigure) {
this.rmqConfigure = rmqConfigure;
}
public MQAdminExt getInstance() throws Exception {
RPCHook rpcHook = null;
final String accessKey = rmqConfigure.getAccessKey();
final String secretKey = rmqConfigure.getSecretKey();
boolean isEnableAcl = StringUtils.isNotEmpty(accessKey) && StringUtils.isNotEmpty(secretKey);
if (isEnableAcl) {
rpcHook = new AclClientRPCHook(new SessionCredentials(accessKey, secretKey));
}
DefaultMQAdminExt mqAdminExt = null;
if (rmqConfigure.getTimeoutMillis() == null) {
mqAdminExt = new DefaultMQAdminExt(rpcHook);
} else {
mqAdminExt = new DefaultMQAdminExt(rpcHook, rmqConfigure.getTimeoutMillis());
}
mqAdminExt.setVipChannelEnabled(Boolean.parseBoolean(rmqConfigure.getIsVIPChannel()));
mqAdminExt.setUseTLS(rmqConfigure.isUseTLS());
mqAdminExt.setInstanceName(Long.toString(System.currentTimeMillis()));
mqAdminExt.start();
log.info("create MQAdmin instance {} success.", mqAdminExt);
return mqAdminExt;
}
}

79
src/main/java/org/apache/rocketmq/dashboard/admin/MQAdminPooledObjectFactory.java

@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.admin;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.rocketmq.common.protocol.body.ClusterInfo;
import org.apache.rocketmq.tools.admin.MQAdminExt;
@Slf4j
public class MQAdminPooledObjectFactory implements PooledObjectFactory<MQAdminExt> {
private MQAdminFactory mqAdminFactory;
@Override
public PooledObject<MQAdminExt> makeObject() throws Exception {
DefaultPooledObject<MQAdminExt> pooledObject = new DefaultPooledObject<>(
mqAdminFactory.getInstance());
return pooledObject;
}
@Override
public void destroyObject(PooledObject<MQAdminExt> p) {
MQAdminExt mqAdmin = p.getObject();
if (mqAdmin != null) {
try {
mqAdmin.shutdown();
} catch (Exception e) {
log.warn("MQAdminExt shutdown err", e);
}
}
log.info("destroy object {}", p.getObject());
}
@Override
public boolean validateObject(PooledObject<MQAdminExt> p) {
MQAdminExt mqAdmin = p.getObject();
ClusterInfo clusterInfo = null;
try {
clusterInfo = mqAdmin.examineBrokerClusterInfo();
} catch (Exception e) {
log.warn("validate object {} err", p.getObject(), e);
}
if (clusterInfo == null || MapUtils.isEmpty(clusterInfo.getBrokerAddrTable())) {
log.warn("validateObject failed, clusterInfo = {}", clusterInfo);
return false;
}
return true;
}
@Override
public void activateObject(PooledObject<MQAdminExt> p) {
}
@Override
public void passivateObject(PooledObject<MQAdminExt> p) {
}
public void setMqAdminFactory(MQAdminFactory mqAdminFactory) {
this.mqAdminFactory = mqAdminFactory;
}
}

47
src/main/java/org/apache/rocketmq/dashboard/admin/MqAdminExtObjectPool.java

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.admin;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MqAdminExtObjectPool {
@Autowired
private RMQConfigure rmqConfigure;
@Bean
public GenericObjectPool<MQAdminExt> mqAdminExtPool() {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setTestWhileIdle(true);
genericObjectPoolConfig.setMaxWaitMillis(10000);
genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(20000);
MQAdminPooledObjectFactory mqAdminPooledObjectFactory = new MQAdminPooledObjectFactory();
MQAdminFactory mqAdminFactory = new MQAdminFactory(rmqConfigure);
mqAdminPooledObjectFactory.setMqAdminFactory(mqAdminFactory);
GenericObjectPool<MQAdminExt> genericObjectPool = new GenericObjectPool<MQAdminExt>(
mqAdminPooledObjectFactory,
genericObjectPoolConfig);
return genericObjectPool;
}
}

59
src/main/java/org/apache/rocketmq/dashboard/aspect/admin/MQAdminAspect.java

@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.aspect.admin;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.rocketmq.dashboard.service.client.MQAdminInstance;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Aspect
@Service
@Slf4j
public class MQAdminAspect {
@Autowired
private GenericObjectPool<MQAdminExt> mqAdminExtPool;
public MQAdminAspect() {
}
@Pointcut("execution(* org.apache.rocketmq.dashboard.service.client.MQAdminExtImpl..*(..))")
public void mQAdminMethodPointCut() {
}
@Around(value = "mQAdminMethodPointCut()")
public Object aroundMQAdminMethod(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object obj = null;
try {
MQAdminInstance.createMQAdmin(mqAdminExtPool);
obj = joinPoint.proceed();
} finally {
MQAdminInstance.returnMQAdmin(mqAdminExtPool);
log.debug("op=look method={} cost={}", joinPoint.getSignature().getName(), System.currentTimeMillis() - start);
}
return obj;
}
}

30
src/main/java/org/apache/rocketmq/dashboard/aspect/admin/annotation/OriginalControllerReturnValue.java

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.aspect.admin.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OriginalControllerReturnValue {
}

90
src/main/java/org/apache/rocketmq/dashboard/config/AuthWebMVCConfigurerAdapter.java

@ -0,0 +1,90 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.config;
import org.apache.rocketmq.dashboard.interceptor.AuthInterceptor;
import org.apache.rocketmq.dashboard.model.UserInfo;
import org.apache.rocketmq.dashboard.util.WebUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Configuration
public class AuthWebMVCConfigurerAdapter extends WebMvcConfigurerAdapter {
@Autowired
@Qualifier("authInterceptor")
private AuthInterceptor authInterceptor;
@Resource
RMQConfigure configure;
@Override
public void addInterceptors(InterceptorRegistry registry) {
if (configure.isLoginRequired()) {
registry.addInterceptor(authInterceptor).addPathPatterns(
"/cluster/**",
"/consumer/**",
"/dashboard/**",
"/message/**",
"/messageTrace/**",
"/monitor/**",
"/rocketmq/**",
"/ops/**",
"/producer/**",
"/test/**",
"/topic/**",
"/config/**");
}
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new HandlerMethodArgumentResolver() {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.getParameterType().isAssignableFrom(UserInfo.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
UserInfo userInfo = (UserInfo) WebUtil.getValueFromSession((HttpServletRequest) nativeWebRequest.getNativeRequest(),
UserInfo.USER_INFO);
if (userInfo != null) {
return userInfo;
}
throw new MissingServletRequestPartException(UserInfo.USER_INFO);
}
});
super.addArgumentResolvers(argumentResolvers); //REVIEW ME
}
}

161
src/main/java/org/apache/rocketmq/dashboard/config/RMQConfigure.java

@ -0,0 +1,161 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.config;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.common.MixAll;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import java.io.File;
import static org.apache.rocketmq.client.ClientConfig.SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY;
@Configuration
@ConfigurationProperties(prefix = "rocketmq.config")
public class RMQConfigure {
private Logger logger = LoggerFactory.getLogger(RMQConfigure.class);
//use rocketmq.namesrv.addr first,if it is empty,than use system proerty or system env
private volatile String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY, System.getenv(MixAll.NAMESRV_ADDR_ENV));
private volatile String isVIPChannel = System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, "true");
private String dataPath = "/tmp/rocketmq-console/data";
private boolean enableDashBoardCollect;
private boolean loginRequired = false;
private String accessKey;
private String secretKey;
private boolean useTLS = false;
private Long timeoutMillis;
public String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getNamesrvAddr() {
return namesrvAddr;
}
public void setNamesrvAddr(String namesrvAddr) {
if (StringUtils.isNotBlank(namesrvAddr)) {
this.namesrvAddr = namesrvAddr;
System.setProperty(MixAll.NAMESRV_ADDR_PROPERTY, namesrvAddr);
logger.info("setNameSrvAddrByProperty nameSrvAddr={}", namesrvAddr);
}
}
public boolean isACLEnabled() {
return !(StringUtils.isAnyBlank(this.accessKey, this.secretKey) ||
StringUtils.isAnyEmpty(this.accessKey, this.secretKey));
}
public String getRocketMqDashboardDataPath() {
return dataPath;
}
public String getDashboardCollectData() {
return dataPath + File.separator + "dashboard";
}
public void setDataPath(String dataPath) {
this.dataPath = dataPath;
}
public String getIsVIPChannel() {
return isVIPChannel;
}
public void setIsVIPChannel(String isVIPChannel) {
if (StringUtils.isNotBlank(isVIPChannel)) {
this.isVIPChannel = isVIPChannel;
System.setProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, isVIPChannel);
logger.info("setIsVIPChannel isVIPChannel={}", isVIPChannel);
}
}
public boolean isEnableDashBoardCollect() {
return enableDashBoardCollect;
}
public void setEnableDashBoardCollect(String enableDashBoardCollect) {
this.enableDashBoardCollect = Boolean.valueOf(enableDashBoardCollect);
}
public boolean isLoginRequired() {
return loginRequired;
}
public void setLoginRequired(boolean loginRequired) {
this.loginRequired = loginRequired;
}
public boolean isUseTLS() {
return useTLS;
}
public void setUseTLS(boolean useTLS) {
this.useTLS = useTLS;
}
public Long getTimeoutMillis() {
return timeoutMillis;
}
public void setTimeoutMillis(Long timeoutMillis) {
this.timeoutMillis = timeoutMillis;
}
// Error Page process logic, move to a central configure later
@Bean
public ErrorPageRegistrar errorPageRegistrar() {
return new MyErrorPageRegistrar();
}
private static class MyErrorPageRegistrar implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
}
}
}

48
src/main/java/org/apache/rocketmq/dashboard/controller/ClusterController.java

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.ClusterService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/cluster")
@Permission
public class ClusterController {
@Resource
private ClusterService clusterService;
@RequestMapping(value = "/list.query", method = RequestMethod.GET)
@ResponseBody
public Object list() {
return clusterService.list();
}
@RequestMapping(value = "/brokerConfig.query", method = RequestMethod.GET)
@ResponseBody
public Object brokerConfig(@RequestParam String brokerAddr) {
return clusterService.getBrokerConfig(brokerAddr);
}
}

62
src/main/java/org/apache/rocketmq/dashboard/controller/ConfigController.java

@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.ConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
@Controller
@RequestMapping("/config")
//@Permission
public class ConfigController {
private Logger logger = LoggerFactory.getLogger(ConfigController.class);
@Resource
private ConfigService configService;
@RequestMapping(value = "/config.query")
@ResponseBody
public Map<String, String> query() {
return configService.queryConfigMap();
}
@RequestMapping(value = "/config.create")
@ResponseBody
public boolean create(String name, String value) {
return configService.createConfig(name, value);
}
@RequestMapping(value = "/config.update")
@ResponseBody
public boolean update(String name, String value) {
return configService.updateConfig(name, value);
}
@RequestMapping(value = "/config.delete")
@ResponseBody
public boolean delete(String name, String value) {
return configService.deleteConfig(name, value);
}
}

120
src/main/java/org/apache/rocketmq/dashboard/controller/ConsumerController.java

@ -0,0 +1,120 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import com.google.common.base.Preconditions;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.rocketmq.common.protocol.body.ConsumerConnection;
import org.apache.rocketmq.dashboard.model.ConnectionInfo;
import org.apache.rocketmq.dashboard.model.request.ConsumerConfigInfo;
import org.apache.rocketmq.dashboard.model.request.DeleteSubGroupRequest;
import org.apache.rocketmq.dashboard.model.request.ResetOffsetRequest;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.ConsumerService;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/consumer")
@Permission
public class ConsumerController {
private Logger logger = LoggerFactory.getLogger(ConsumerController.class);
@Resource
private ConsumerService consumerService;
@RequestMapping(value = "/groupList.query")
@ResponseBody
public Object list() {
return consumerService.queryGroupList();
}
@RequestMapping(value = "/group.query")
@ResponseBody
public Object groupQuery(@RequestParam String consumerGroup) {
return consumerService.queryGroup(consumerGroup);
}
@RequestMapping(value = "/resetOffset.do", method = {RequestMethod.POST})
@ResponseBody
public Object resetOffset(@RequestBody ResetOffsetRequest resetOffsetRequest) {
logger.info("op=look resetOffsetRequest={}", JsonUtil.obj2String(resetOffsetRequest));
return consumerService.resetOffset(resetOffsetRequest);
}
@RequestMapping(value = "/skipAccumulate.do", method = {RequestMethod.POST})
@ResponseBody
public Object skipAccumulate(@RequestBody ResetOffsetRequest resetOffsetRequest) {
logger.info("op=look resetOffsetRequest={}", JsonUtil.obj2String(resetOffsetRequest));
return consumerService.resetOffset(resetOffsetRequest);
}
@RequestMapping(value = "/examineSubscriptionGroupConfig.query")
@ResponseBody
public Object examineSubscriptionGroupConfig(@RequestParam String consumerGroup) {
return consumerService.examineSubscriptionGroupConfig(consumerGroup);
}
@RequestMapping(value = "/deleteSubGroup.do", method = {RequestMethod.POST})
@ResponseBody
public Object deleteSubGroup(@RequestBody DeleteSubGroupRequest deleteSubGroupRequest) {
return consumerService.deleteSubGroup(deleteSubGroupRequest);
}
@RequestMapping(value = "/createOrUpdate.do", method = {RequestMethod.POST})
@ResponseBody
public Object consumerCreateOrUpdateRequest(@RequestBody ConsumerConfigInfo consumerConfigInfo) {
Preconditions.checkArgument(CollectionUtils.isNotEmpty(consumerConfigInfo.getBrokerNameList()) || CollectionUtils.isNotEmpty(consumerConfigInfo.getClusterNameList()),
"clusterName or brokerName can not be all blank");
return consumerService.createAndUpdateSubscriptionGroupConfig(consumerConfigInfo);
}
@RequestMapping(value = "/fetchBrokerNameList.query", method = {RequestMethod.GET})
@ResponseBody
public Object fetchBrokerNameList(@RequestParam String consumerGroup) {
return consumerService.fetchBrokerNameSetBySubscriptionGroup(consumerGroup);
}
@RequestMapping(value = "/queryTopicByConsumer.query")
@ResponseBody
public Object queryConsumerByTopic(@RequestParam String consumerGroup) {
return consumerService.queryConsumeStatsListByGroupName(consumerGroup);
}
@RequestMapping(value = "/consumerConnection.query")
@ResponseBody
public Object consumerConnection(@RequestParam(required = false) String consumerGroup) {
ConsumerConnection consumerConnection = consumerService.getConsumerConnection(consumerGroup);
consumerConnection.setConnectionSet(ConnectionInfo.buildConnectionInfoHashSet(consumerConnection.getConnectionSet()));
return consumerConnection;
}
@RequestMapping(value = "/consumerRunningInfo.query")
@ResponseBody
public Object getConsumerRunningInfo(@RequestParam String consumerGroup, @RequestParam String clientId,
@RequestParam boolean jstack) {
return consumerService.getConsumerRunningInfo(consumerGroup, clientId, jstack);
}
}

60
src/main/java/org/apache/rocketmq/dashboard/controller/DashboardController.java

@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import javax.annotation.Resource;
import com.google.common.base.Strings;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.DashboardService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/dashboard")
@Permission
public class DashboardController {
@Resource
DashboardService dashboardService;
@RequestMapping(value = "/broker.query", method = RequestMethod.GET)
@ResponseBody
public Object broker(@RequestParam String date) {
return dashboardService.queryBrokerData(date);
}
@RequestMapping(value = "/topic.query", method = RequestMethod.GET)
@ResponseBody
public Object topic(@RequestParam String date, String topicName) {
if (Strings.isNullOrEmpty(topicName)) {
return dashboardService.queryTopicData(date);
}
return dashboardService.queryTopicData(date,topicName);
}
@RequestMapping(value = "/topicCurrent", method = RequestMethod.GET)
@ResponseBody
public Object topicCurrent() {
return dashboardService.queryTopicCurrentData();
}
}

95
src/main/java/org/apache/rocketmq/dashboard/controller/LoginController.java

@ -0,0 +1,95 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.model.LoginInfo;
import org.apache.rocketmq.dashboard.model.LoginResult;
import org.apache.rocketmq.dashboard.model.User;
import org.apache.rocketmq.dashboard.model.UserInfo;
import org.apache.rocketmq.dashboard.service.UserService;
import org.apache.rocketmq.dashboard.support.JsonResult;
import org.apache.rocketmq.dashboard.util.WebUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/login")
public class LoginController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private RMQConfigure configure;
@Autowired
private UserService userService;
@Value("${server.servlet.context-path:/}")
private String contextPath;
@RequestMapping(value = "/check.query", method = RequestMethod.GET)
@ResponseBody
public Object check(HttpServletRequest request) {
LoginInfo loginInfo = new LoginInfo();
loginInfo.setLogined(WebUtil.getValueFromSession(request, WebUtil.USER_NAME) != null);
loginInfo.setLoginRequired(configure.isLoginRequired());
return loginInfo;
}
@RequestMapping(value = "/login.do", method = RequestMethod.POST)
@ResponseBody
public Object login(@RequestParam("username") String username,
@RequestParam(value = "password") String password,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
logger.info("user:{} login", username);
User user = userService.queryByUsernameAndPassword(username, password);
if (user == null) {
throw new IllegalArgumentException("Bad username or password!");
} else {
user.setPassword(null);
UserInfo userInfo = WebUtil.setLoginInfo(request, response, user);
WebUtil.setSessionValue(request, WebUtil.USER_INFO, userInfo);
WebUtil.setSessionValue(request, WebUtil.USER_NAME, username);
userInfo.setSessionId(WebUtil.getSessionId(request));
LoginResult result = new LoginResult(username, user.getType(), contextPath);
return result;
}
}
@RequestMapping(value = "/logout.do", method = RequestMethod.POST)
@ResponseBody
public JsonResult<String> logout(HttpServletRequest request) {
WebUtil.removeSession(request);
return new JsonResult<>(contextPath);
}
}

90
src/main/java/org/apache/rocketmq/dashboard/controller/MessageController.java

@ -0,0 +1,90 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import com.google.common.collect.Maps;
import org.apache.rocketmq.common.Pair;
import org.apache.rocketmq.common.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.dashboard.model.MessagePage;
import org.apache.rocketmq.dashboard.model.MessageView;
import org.apache.rocketmq.dashboard.model.request.MessageQuery;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.MessageService;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.tools.admin.api.MessageTrack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/message")
@Permission
public class MessageController {
private Logger logger = LoggerFactory.getLogger(MessageController.class);
@Resource
private MessageService messageService;
@RequestMapping(value = "/viewMessage.query", method = RequestMethod.GET)
@ResponseBody
public Object viewMessage(@RequestParam(required = false) String topic, @RequestParam String msgId) {
Map<String, Object> messageViewMap = Maps.newHashMap();
Pair<MessageView, List<MessageTrack>> messageViewListPair = messageService.viewMessage(topic, msgId);
messageViewMap.put("messageView", messageViewListPair.getObject1());
messageViewMap.put("messageTrackList", messageViewListPair.getObject2());
return messageViewMap;
}
@PostMapping("/queryMessagePageByTopic.query")
@ResponseBody
public MessagePage queryMessagePageByTopic(@RequestBody MessageQuery query) {
return messageService.queryMessageByPage(query);
}
@RequestMapping(value = "/queryMessageByTopicAndKey.query", method = RequestMethod.GET)
@ResponseBody
public Object queryMessageByTopicAndKey(@RequestParam String topic, @RequestParam String key) {
return messageService.queryMessageByTopicAndKey(topic, key);
}
@RequestMapping(value = "/queryMessageByTopic.query", method = RequestMethod.GET)
@ResponseBody
public Object queryMessageByTopic(@RequestParam String topic, @RequestParam long begin,
@RequestParam long end) {
return messageService.queryMessageByTopic(topic, begin, end);
}
@RequestMapping(value = "/consumeMessageDirectly.do", method = RequestMethod.POST)
@ResponseBody
public Object consumeMessageDirectly(@RequestParam String topic, @RequestParam String consumerGroup,
@RequestParam String msgId,
@RequestParam(required = false) String clientId) {
logger.info("msgId={} consumerGroup={} clientId={}", msgId, consumerGroup, clientId);
ConsumeMessageDirectlyResult consumeMessageDirectlyResult = messageService.consumeMessageDirectly(topic, msgId, consumerGroup, clientId);
logger.info("consumeMessageDirectlyResult={}", JsonUtil.obj2String(consumeMessageDirectlyResult));
return consumeMessageDirectlyResult;
}
}

71
src/main/java/org/apache/rocketmq/dashboard/controller/MessageTraceController.java

@ -0,0 +1,71 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.rocketmq.common.Pair;
import org.apache.rocketmq.dashboard.model.MessageView;
import org.apache.rocketmq.dashboard.model.trace.MessageTraceGraph;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.MessageService;
import org.apache.rocketmq.dashboard.service.MessageTraceService;
import org.apache.rocketmq.tools.admin.api.MessageTrack;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/messageTrace")
@Permission
public class MessageTraceController {
@Resource
private MessageService messageService;
@Resource
private MessageTraceService messageTraceService;
@RequestMapping(value = "/viewMessage.query", method = RequestMethod.GET)
@ResponseBody
public Object viewMessage(@RequestParam(required = false) String topic, @RequestParam String msgId) {
Map<String, Object> messageViewMap = Maps.newHashMap();
Pair<MessageView, List<MessageTrack>> messageViewListPair = messageService.viewMessage(topic, msgId);
messageViewMap.put("messageView", messageViewListPair.getObject1());
return messageViewMap;
}
@RequestMapping(value = "/viewMessageTraceDetail.query", method = RequestMethod.GET)
@ResponseBody
public Object viewTraceMessages(@RequestParam String msgId) {
return messageTraceService.queryMessageTraceKey(msgId);
}
@RequestMapping(value = "/viewMessageTraceGraph.query", method = RequestMethod.GET)
@ResponseBody
public MessageTraceGraph viewMessageTraceGraph(@RequestParam String msgId,
@RequestParam(required = false) String traceTopic) {
return messageTraceService.queryMessageTraceGraph(msgId, traceTopic);
}
}

64
src/main/java/org/apache/rocketmq/dashboard/controller/MonitorController.java

@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.MonitorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/monitor")
@Permission
public class MonitorController {
private Logger logger = LoggerFactory.getLogger(MonitorController.class);
@Resource
private MonitorService monitorService;
@RequestMapping(value = "/createOrUpdateConsumerMonitor.do", method = {RequestMethod.POST})
@ResponseBody
public Object createOrUpdateConsumerMonitor(@RequestParam String consumeGroupName, @RequestParam int minCount,
@RequestParam int maxDiffTotal) {
return monitorService.createOrUpdateConsumerMonitor(consumeGroupName, new ConsumerMonitorConfig(minCount, maxDiffTotal));
}
@RequestMapping(value = "/consumerMonitorConfig.query", method = {RequestMethod.GET})
@ResponseBody
public Object consumerMonitorConfig() {
return monitorService.queryConsumerMonitorConfig();
}
@RequestMapping(value = "/consumerMonitorConfigByGroupName.query", method = {RequestMethod.GET})
@ResponseBody
public Object consumerMonitorConfigByGroupName(@RequestParam String consumeGroupName) {
return monitorService.queryConsumerMonitorConfigByGroupName(consumeGroupName);
}
@RequestMapping(value = "/deleteConsumerMonitor.do", method = {RequestMethod.POST})
@ResponseBody
public Object deleteConsumerMonitor(@RequestParam String consumeGroupName) {
return monitorService.deleteConsumerMonitor(consumeGroupName);
}
}

41
src/main/java/org/apache/rocketmq/dashboard/controller/NamesvrController.java

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.aspect.admin.annotation.OriginalControllerReturnValue;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.OpsService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/rocketmq")
@Permission
public class NamesvrController {
@Resource
private OpsService opsService;
@RequestMapping(value = "/nsaddr", method = RequestMethod.GET)
@ResponseBody
@OriginalControllerReturnValue
public Object nsaddr() {
return opsService.getNameSvrList();
}
}

70
src/main/java/org/apache/rocketmq/dashboard/controller/OpsController.java

@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.OpsService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/ops")
@Permission
public class OpsController {
@Resource
private OpsService opsService;
@RequestMapping(value = "/homePage.query", method = RequestMethod.GET)
@ResponseBody
public Object homePage() {
return opsService.homePageInfo();
}
@RequestMapping(value = "/updateNameSvrAddr.do", method = RequestMethod.POST)
@ResponseBody
public Object updateNameSvrAddr(@RequestParam String nameSvrAddrList) {
opsService.updateNameSvrAddrList(nameSvrAddrList);
return true;
}
@RequestMapping(value = "/updateIsVIPChannel.do", method = RequestMethod.POST)
@ResponseBody
public Object updateIsVIPChannel(@RequestParam String useVIPChannel) {
opsService.updateIsVIPChannel(useVIPChannel);
return true;
}
@RequestMapping(value = "/rocketMqStatus.query", method = RequestMethod.GET)
@ResponseBody
public Object clusterStatus() {
return opsService.rocketMqStatusCheck();
}
@RequestMapping(value = "/updateUseTLS.do", method = RequestMethod.POST)
@ResponseBody
public Object updateUseTLS(@RequestParam String useTLS) {
opsService.updateUseTLS(Boolean.parseBoolean(useTLS));
return true;
}
}

45
src/main/java/org/apache/rocketmq/dashboard/controller/ProducerController.java

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import javax.annotation.Resource;
import org.apache.rocketmq.common.protocol.body.ProducerConnection;
import org.apache.rocketmq.dashboard.model.ConnectionInfo;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.ProducerService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/producer")
@Permission
public class ProducerController {
@Resource
private ProducerService producerService;
@RequestMapping(value = "/producerConnection.query", method = {RequestMethod.GET})
@ResponseBody
public Object producerConnection(@RequestParam String producerGroup, @RequestParam String topic) {
ProducerConnection producerConnection = producerService.getProducerConnection(producerGroup, topic);
producerConnection.setConnectionSet(ConnectionInfo.buildConnectionInfoHashSet(producerConnection.getConnectionSet()));
return producerConnection;
}
}

101
src/main/java/org/apache/rocketmq/dashboard/controller/TestController.java

@ -0,0 +1,101 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.util.List;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/test")
public class TestController {
private Logger logger = LoggerFactory.getLogger(TestController.class);
private String testTopic = "TestTopic";
@Resource
private RMQConfigure rMQConfigure;
@RequestMapping(value = "/runTask.do", method = RequestMethod.GET)
@ResponseBody
public Object list() throws MQClientException, RemotingException, InterruptedException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(testTopic + "Group");
consumer.setNamesrvAddr(rMQConfigure.getNamesrvAddr());
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.subscribe(testTopic, "*");
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
logger.info("receiveMessage msgSize={}", msgs.size());
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
final DefaultMQProducer producer = new DefaultMQProducer(testTopic + "Group");
producer.setInstanceName(String.valueOf(System.currentTimeMillis()));
producer.setNamesrvAddr(rMQConfigure.getNamesrvAddr());
producer.start();
new Thread(new Runnable() {
@Override public void run() {
int i = 0;
while (true) {
try {
Message msg = new Message(testTopic,
"TagA" + i,
"KEYS" + i,
("Hello RocketMQ " + i).getBytes()
);
Thread.sleep(1000L);
SendResult sendResult = producer.send(msg);
logger.info("sendMessage={}", JsonUtil.obj2String(sendResult));
}
catch (Exception e) {
e.printStackTrace();
try {
Thread.sleep(1000);
}
catch (Exception ignore) {
}
}
}
}
}).start();
return true;
}
}

120
src/main/java/org/apache/rocketmq/dashboard/controller/TopicController.java

@ -0,0 +1,120 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.controller;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.dashboard.model.request.SendTopicMessageRequest;
import org.apache.rocketmq.dashboard.model.request.TopicConfigInfo;
import org.apache.rocketmq.dashboard.service.ConsumerService;
import org.apache.rocketmq.dashboard.service.TopicService;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import com.google.common.base.Preconditions;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/topic")
@Permission
public class TopicController {
private Logger logger = LoggerFactory.getLogger(TopicController.class);
@Resource
private TopicService topicService;
@Resource
private ConsumerService consumerService;
@RequestMapping(value = "/list.query", method = RequestMethod.GET)
@ResponseBody
public Object list(@RequestParam(value = "skipSysProcess", required = false) boolean skipSysProcess,
@RequestParam(value = "skipRetryAndDlq", required = false) boolean skipRetryAndDlq) {
return topicService.fetchAllTopicList(skipSysProcess, skipRetryAndDlq);
}
@RequestMapping(value = "/stats.query", method = RequestMethod.GET)
@ResponseBody
public Object stats(@RequestParam String topic) {
return topicService.stats(topic);
}
@RequestMapping(value = "/route.query", method = RequestMethod.GET)
@ResponseBody
public Object route(@RequestParam String topic) {
return topicService.route(topic);
}
@RequestMapping(value = "/createOrUpdate.do", method = { RequestMethod.POST})
@ResponseBody
public Object topicCreateOrUpdateRequest(@RequestBody TopicConfigInfo topicCreateOrUpdateRequest) {
Preconditions.checkArgument(CollectionUtils.isNotEmpty(topicCreateOrUpdateRequest.getBrokerNameList()) || CollectionUtils.isNotEmpty(topicCreateOrUpdateRequest.getClusterNameList()),
"clusterName or brokerName can not be all blank");
logger.info("op=look topicCreateOrUpdateRequest={}", JsonUtil.obj2String(topicCreateOrUpdateRequest));
topicService.createOrUpdate(topicCreateOrUpdateRequest);
return true;
}
@RequestMapping(value = "/queryConsumerByTopic.query")
@ResponseBody
public Object queryConsumerByTopic(@RequestParam String topic) {
return consumerService.queryConsumeStatsListByTopicName(topic);
}
@RequestMapping(value = "/queryTopicConsumerInfo.query")
@ResponseBody
public Object queryTopicConsumerInfo(@RequestParam String topic) {
return topicService.queryTopicConsumerInfo(topic);
}
@RequestMapping(value = "/examineTopicConfig.query")
@ResponseBody
public Object examineTopicConfig(@RequestParam String topic,
@RequestParam(required = false) String brokerName) throws RemotingException, MQClientException, InterruptedException {
return topicService.examineTopicConfig(topic);
}
@RequestMapping(value = "/sendTopicMessage.do", method = {RequestMethod.POST})
@ResponseBody
public Object sendTopicMessage(
@RequestBody SendTopicMessageRequest sendTopicMessageRequest) throws RemotingException, MQClientException, InterruptedException {
return topicService.sendTopicMessageRequest(sendTopicMessageRequest);
}
@RequestMapping(value = "/deleteTopic.do", method = {RequestMethod.POST})
@ResponseBody
public Object delete(@RequestParam(required = false) String clusterName, @RequestParam String topic) {
return topicService.deleteTopic(topic, clusterName);
}
@RequestMapping(value = "/deleteTopicByBroker.do", method = {RequestMethod.POST})
@ResponseBody
public Object deleteTopicByBroker(@RequestParam String brokerName, @RequestParam String topic) {
return topicService.deleteTopicInBroker(brokerName, topic);
}
}

31
src/main/java/org/apache/rocketmq/dashboard/exception/ServiceException.java

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.exception;
public class ServiceException extends RuntimeException {
private static final long serialVersionUID = 9213584003139969215L;
private int code;
public ServiceException(int code, String message) {
super(message);
this.code = code;
}
public int getCode() {
return code;
}
}

51
src/main/java/org/apache/rocketmq/dashboard/filter/HttpBasicAuthorizedFilter.java

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
@WebFilter(urlPatterns = "/*", filterName = "httpBasicAuthorizedFilter")
public class HttpBasicAuthorizedFilter implements Filter {
@Override
public void init(FilterConfig config) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setContentType("application/json; charset=utf-8");
httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"rocketmq\"");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}

38
src/main/java/org/apache/rocketmq/dashboard/interceptor/AuthInterceptor.java

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.interceptor;
import org.apache.rocketmq.dashboard.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
@Autowired
private LoginService loginService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return loginService.login(request, response);
}
}

53
src/main/java/org/apache/rocketmq/dashboard/model/ConnectionInfo.java

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.HashSet;
import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.common.protocol.body.Connection;
public class ConnectionInfo extends Connection {
private String versionDesc;
public static ConnectionInfo buildConnectionInfo(Connection connection) {
ConnectionInfo connectionInfo = new ConnectionInfo();
connectionInfo.setClientId(connection.getClientId());
connectionInfo.setClientAddr(connection.getClientAddr());
connectionInfo.setLanguage(connection.getLanguage());
connectionInfo.setVersion(connection.getVersion());
connectionInfo.setVersionDesc(MQVersion.getVersionDesc(connection.getVersion()));
return connectionInfo;
}
public static HashSet<Connection> buildConnectionInfoHashSet(Collection<Connection> connectionList) {
HashSet<Connection> connectionHashSet = Sets.newHashSet();
for (Connection connection : connectionList) {
connectionHashSet.add(buildConnectionInfo(connection));
}
return connectionHashSet;
}
public String getVersionDesc() {
return versionDesc;
}
public void setVersionDesc(String versionDesc) {
this.versionDesc = versionDesc;
}
}

61
src/main/java/org/apache/rocketmq/dashboard/model/ConsumerGroupRollBackStat.java

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import org.apache.rocketmq.common.admin.RollbackStats;
import com.google.common.collect.Lists;
import java.util.List;
public class ConsumerGroupRollBackStat {
private boolean status;
private String errMsg;
private List<RollbackStats> rollbackStatsList = Lists.newArrayList();
public ConsumerGroupRollBackStat(boolean status) {
this.status = status;
}
public ConsumerGroupRollBackStat(boolean status, String errMsg) {
this.status = status;
this.errMsg = errMsg;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public List<RollbackStats> getRollbackStatsList() {
return rollbackStatsList;
}
public void setRollbackStatsList(List<RollbackStats> rollbackStatsList) {
this.rollbackStatsList = rollbackStatsList;
}
}

46
src/main/java/org/apache/rocketmq/dashboard/model/ConsumerMonitorConfig.java

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
public class ConsumerMonitorConfig {
private int minCount;
private int maxDiffTotal;
public ConsumerMonitorConfig() {
}
public ConsumerMonitorConfig(int minCount, int maxDiffTotal) {
this.minCount = minCount;
this.maxDiffTotal = maxDiffTotal;
}
public int getMinCount() {
return minCount;
}
public void setMinCount(int minCount) {
this.minCount = minCount;
}
public int getMaxDiffTotal() {
return maxDiffTotal;
}
public void setMaxDiffTotal(int maxDiffTotal) {
this.maxDiffTotal = maxDiffTotal;
}
}

94
src/main/java/org/apache/rocketmq/dashboard/model/GroupConsumeInfo.java

@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import org.apache.rocketmq.common.protocol.heartbeat.ConsumeType;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
public class GroupConsumeInfo implements Comparable<GroupConsumeInfo> {
private String group;
private String version;
private int count;
private ConsumeType consumeType;
private MessageModel messageModel;
private int consumeTps;
private long diffTotal = -1;
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public ConsumeType getConsumeType() {
return consumeType;
}
public void setConsumeType(ConsumeType consumeType) {
this.consumeType = consumeType;
}
public MessageModel getMessageModel() {
return messageModel;
}
public void setMessageModel(MessageModel messageModel) {
this.messageModel = messageModel;
}
public long getDiffTotal() {
return diffTotal;
}
public void setDiffTotal(long diffTotal) {
this.diffTotal = diffTotal;
}
@Override
public int compareTo(GroupConsumeInfo o) {
if (this.count != o.count) {
return Integer.compare(o.count, this.count);
}
return Long.compare(o.diffTotal, this.diffTotal);
}
public int getConsumeTps() {
return consumeTps;
}
public void setConsumeTps(int consumeTps) {
this.consumeTps = consumeTps;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}

39
src/main/java/org/apache/rocketmq/dashboard/model/LoginInfo.java

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
public class LoginInfo {
private boolean loginRequired;
private boolean logined;
public boolean isLoginRequired() {
return loginRequired;
}
public void setLoginRequired(boolean loginRequired) {
this.loginRequired = loginRequired;
}
public boolean isLogined() {
return logined;
}
public void setLogined(boolean logined) {
this.logined = logined;
}
}

36
src/main/java/org/apache/rocketmq/dashboard/model/LoginResult.java

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginResult {
private String loginUserName;
/**
* 0: normal 1: admin
*/
private int loginUserRole;
private String contextPath;
}

54
src/main/java/org/apache/rocketmq/dashboard/model/MessagePage.java

@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import org.springframework.data.domain.Page;
public class MessagePage {
private Page<MessageView> page;
private String taskId;
public MessagePage(Page<MessageView> page, String taskId) {
this.page = page;
this.taskId = taskId;
}
public Page<MessageView> getPage() {
return page;
}
public void setPage(Page<MessageView> page) {
this.page = page;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
@Override
public String toString() {
return "MessagePage{" +
"page=" + page +
", taskId='" + taskId + '\'' +
'}';
}
}

55
src/main/java/org/apache/rocketmq/dashboard/model/MessagePageTask.java

@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import org.springframework.data.domain.Page;
import java.util.List;
public class MessagePageTask {
private Page<MessageView> page;
private List<QueueOffsetInfo> queueOffsetInfos;
public MessagePageTask(Page<MessageView> page, List<QueueOffsetInfo> queueOffsetInfos) {
this.page = page;
this.queueOffsetInfos = queueOffsetInfos;
}
public Page<MessageView> getPage() {
return page;
}
public void setPage(Page<MessageView> page) {
this.page = page;
}
public List<QueueOffsetInfo> getQueueOffsetInfos() {
return queueOffsetInfos;
}
public void setQueueOffsetInfos(List<QueueOffsetInfo> queueOffsetInfos) {
this.queueOffsetInfos = queueOffsetInfos;
}
@Override
public String toString() {
return "MessagePageTask{" +
"page=" + page +
", queueOffsetInfos=" + queueOffsetInfos +
'}';
}
}

107
src/main/java/org/apache/rocketmq/dashboard/model/MessageQueryByPage.java

@ -0,0 +1,107 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import org.springframework.data.domain.PageRequest;
public class MessageQueryByPage {
public static final int DEFAULT_PAGE = 0;
public static final int MIN_PAGE_SIZE = 10;
public static final int MAX_PAGE_SIZE = 100;
/**
* current page num
*/
private int pageNum;
private int pageSize;
private String topic;
private long begin;
private long end;
public MessageQueryByPage(int pageNum, int pageSize, String topic, long begin, long end) {
this.pageNum = pageNum;
this.pageSize = pageSize;
this.topic = topic;
this.begin = begin;
this.end = end;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public long getBegin() {
return begin;
}
public void setBegin(long begin) {
this.begin = begin;
}
public long getEnd() {
return end;
}
public void setEnd(long end) {
this.end = end;
}
public int getPageNum() {
return pageNum <= 0 ? DEFAULT_PAGE : pageNum - 1;
}
public int getPageSize() {
if (pageSize <= 1) {
return MIN_PAGE_SIZE;
} else if (pageSize > MAX_PAGE_SIZE) {
return MAX_PAGE_SIZE;
}
return this.pageSize;
}
public PageRequest page() {
return PageRequest.of(this.getPageNum(), this.getPageSize());
}
@Override
public String toString() {
return "MessageQueryByPage{" +
"pageNum=" + pageNum +
", pageSize=" + pageSize +
", topic='" + topic + '\'' +
", begin=" + begin +
", end=" + end +
'}';
}
}

237
src/main/java/org/apache/rocketmq/dashboard/model/MessageTraceView.java

@ -0,0 +1,237 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import com.google.common.base.Charsets;
import org.apache.rocketmq.client.trace.TraceBean;
import org.apache.rocketmq.client.trace.TraceContext;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.dashboard.model.trace.MessageTraceStatusEnum;
import org.apache.rocketmq.dashboard.util.MsgTraceDecodeUtil;
import java.util.ArrayList;
import java.util.List;
public class MessageTraceView {
private String requestId;
private String msgId;
private String tags;
private String keys;
private String storeHost;
private String clientHost;
private int costTime;
private String msgType;
private String offSetMsgId;
private long timeStamp;
private String topic;
private String groupName;
private int retryTimes;
private String status;
private String transactionState;
private String transactionId;
private boolean fromTransactionCheck;
private String traceType;
public MessageTraceView() {
}
public static List<MessageTraceView> decodeFromTraceTransData(String key, MessageExt messageExt) {
List<MessageTraceView> messageTraceViewList = new ArrayList<MessageTraceView>();
String messageBody = new String(messageExt.getBody(), Charsets.UTF_8);
if (messageBody == null || messageBody.length() <= 0) {
return messageTraceViewList;
}
List<TraceContext> traceContextList = MsgTraceDecodeUtil.decoderFromTraceDataString(messageBody);
for (TraceContext context : traceContextList) {
MessageTraceView messageTraceView = new MessageTraceView();
TraceBean traceBean = context.getTraceBeans().get(0);
if (!traceBean.getMsgId().equals(key)) {
continue;
}
messageTraceView.setCostTime(context.getCostTime());
messageTraceView.setGroupName(context.getGroupName());
if (context.isSuccess()) {
messageTraceView.setStatus(MessageTraceStatusEnum.SUCCESS.getStatus());
} else {
messageTraceView.setStatus(MessageTraceStatusEnum.FAILED.getStatus());
}
messageTraceView.setKeys(traceBean.getKeys());
messageTraceView.setMsgId(traceBean.getMsgId());
messageTraceView.setTags(traceBean.getTags());
messageTraceView.setTopic(traceBean.getTopic());
messageTraceView.setMsgType(traceBean.getMsgType() == null ? null : traceBean.getMsgType().name());
messageTraceView.setOffSetMsgId(traceBean.getOffsetMsgId());
messageTraceView.setTimeStamp(context.getTimeStamp());
messageTraceView.setStoreHost(traceBean.getStoreHost());
messageTraceView.setClientHost(messageExt.getBornHostString());
messageTraceView.setRequestId(context.getRequestId());
messageTraceView.setRetryTimes(traceBean.getRetryTimes());
messageTraceView.setTransactionState(traceBean.getTransactionState() == null ? null : traceBean.getTransactionState().name());
messageTraceView.setTransactionId(traceBean.getTransactionId());
messageTraceView.setFromTransactionCheck(traceBean.isFromTransactionCheck());
messageTraceView.setTraceType(context.getTraceType() == null ? null : context.getTraceType().name());
messageTraceViewList.add(messageTraceView);
}
return messageTraceViewList;
}
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public String getKeys() {
return keys;
}
public void setKeys(String keys) {
this.keys = keys;
}
public String getStoreHost() {
return storeHost;
}
public void setStoreHost(String storeHost) {
this.storeHost = storeHost;
}
public int getCostTime() {
return costTime;
}
public void setCostTime(int costTime) {
this.costTime = costTime;
}
public String getMsgType() {
return msgType;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
public String getOffSetMsgId() {
return offSetMsgId;
}
public void setOffSetMsgId(String offSetMsgId) {
this.offSetMsgId = offSetMsgId;
}
public long getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getClientHost() {
return clientHost;
}
public void setClientHost(String clientHost) {
this.clientHost = clientHost;
}
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
public int getRetryTimes() {
return retryTimes;
}
public void setRetryTimes(int retryTimes) {
this.retryTimes = retryTimes;
}
public String getTransactionState() {
return transactionState;
}
public void setTransactionState(String transactionState) {
this.transactionState = transactionState;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public boolean isFromTransactionCheck() {
return fromTransactionCheck;
}
public void setFromTransactionCheck(boolean fromTransactionCheck) {
this.fromTransactionCheck = fromTransactionCheck;
}
public String getTraceType() {
return traceType;
}
public void setTraceType(String traceType) {
this.traceType = traceType;
}
}

196
src/main/java/org/apache/rocketmq/dashboard/model/MessageView.java

@ -0,0 +1,196 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import org.apache.rocketmq.common.message.MessageExt;
import com.google.common.base.Charsets;
import org.springframework.beans.BeanUtils;
import java.net.SocketAddress;
import java.util.Map;
public class MessageView {
/** from MessageExt **/
private int queueId;
private int storeSize;
private long queueOffset;
private int sysFlag;
private long bornTimestamp;
private SocketAddress bornHost;
private long storeTimestamp;
private SocketAddress storeHost;
private String msgId;
private long commitLogOffset;
private int bodyCRC;
private int reconsumeTimes;
private long preparedTransactionOffset;
/**from MessageExt**/
/** from Message **/
private String topic;
private int flag;
private Map<String, String> properties;
private String messageBody; // body
/** from Message **/
public static MessageView fromMessageExt(MessageExt messageExt) {
MessageView messageView = new MessageView();
BeanUtils.copyProperties(messageExt, messageView);
if (messageExt.getBody() != null) {
messageView.setMessageBody(new String(messageExt.getBody(), Charsets.UTF_8));
}
return messageView;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
}
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
public int getQueueId() {
return queueId;
}
public void setQueueId(int queueId) {
this.queueId = queueId;
}
public int getStoreSize() {
return storeSize;
}
public void setStoreSize(int storeSize) {
this.storeSize = storeSize;
}
public long getQueueOffset() {
return queueOffset;
}
public void setQueueOffset(long queueOffset) {
this.queueOffset = queueOffset;
}
public int getSysFlag() {
return sysFlag;
}
public void setSysFlag(int sysFlag) {
this.sysFlag = sysFlag;
}
public long getBornTimestamp() {
return bornTimestamp;
}
public void setBornTimestamp(long bornTimestamp) {
this.bornTimestamp = bornTimestamp;
}
public SocketAddress getBornHost() {
return bornHost;
}
public void setBornHost(SocketAddress bornHost) {
this.bornHost = bornHost;
}
public long getStoreTimestamp() {
return storeTimestamp;
}
public void setStoreTimestamp(long storeTimestamp) {
this.storeTimestamp = storeTimestamp;
}
public SocketAddress getStoreHost() {
return storeHost;
}
public void setStoreHost(SocketAddress storeHost) {
this.storeHost = storeHost;
}
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
public long getCommitLogOffset() {
return commitLogOffset;
}
public void setCommitLogOffset(long commitLogOffset) {
this.commitLogOffset = commitLogOffset;
}
public int getBodyCRC() {
return bodyCRC;
}
public void setBodyCRC(int bodyCRC) {
this.bodyCRC = bodyCRC;
}
public int getReconsumeTimes() {
return reconsumeTimes;
}
public void setReconsumeTimes(int reconsumeTimes) {
this.reconsumeTimes = reconsumeTimes;
}
public long getPreparedTransactionOffset() {
return preparedTransactionOffset;
}
public void setPreparedTransactionOffset(long preparedTransactionOffset) {
this.preparedTransactionOffset = preparedTransactionOffset;
}
public String getMessageBody() {
return messageBody;
}
public void setMessageBody(String messageBody) {
this.messageBody = messageBody;
}
}

104
src/main/java/org/apache/rocketmq/dashboard/model/QueueOffsetInfo.java

@ -0,0 +1,104 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import org.apache.rocketmq.common.message.MessageQueue;
public class QueueOffsetInfo {
private Integer idx;
private Long start;
private Long end;
private Long startOffset;
private Long endOffset;
private MessageQueue messageQueues;
public QueueOffsetInfo() {
}
public QueueOffsetInfo(Integer idx, Long start, Long end, Long startOffset, Long endOffset, MessageQueue messageQueues) {
this.idx = idx;
this.start = start;
this.end = end;
this.startOffset = startOffset;
this.endOffset = endOffset;
this.messageQueues = messageQueues;
}
public Integer getIdx() {
return idx;
}
public void setIdx(Integer idx) {
this.idx = idx;
}
public Long getStart() {
return start;
}
public void setStart(Long start) {
this.start = start;
}
public Long getEnd() {
return end;
}
public void setEnd(Long end) {
this.end = end;
}
public Long getStartOffset() {
return startOffset;
}
public void setStartOffset(Long startOffset) {
this.startOffset = startOffset;
}
public Long getEndOffset() {
return endOffset;
}
public void setEndOffset(Long endOffset) {
this.endOffset = endOffset;
}
public MessageQueue getMessageQueues() {
return messageQueues;
}
public void setMessageQueues(MessageQueue messageQueues) {
this.messageQueues = messageQueues;
}
public void incStartOffset() {
this.startOffset++;
this.endOffset++;
}
public void incEndOffset() {
this.endOffset++;
}
public void incStartOffset(long size) {
this.startOffset += size;
this.endOffset += size;
}
}

85
src/main/java/org/apache/rocketmq/dashboard/model/QueueStatInfo.java

@ -0,0 +1,85 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import org.apache.rocketmq.common.admin.OffsetWrapper;
import org.apache.rocketmq.common.message.MessageQueue;
import org.springframework.beans.BeanUtils;
public class QueueStatInfo {
private String brokerName;
private int queueId;
private long brokerOffset;
private long consumerOffset;
private String clientInfo;
private long lastTimestamp;
public static QueueStatInfo fromOffsetTableEntry(MessageQueue key, OffsetWrapper value) {
QueueStatInfo queueStatInfo = new QueueStatInfo();
BeanUtils.copyProperties(key, queueStatInfo);
BeanUtils.copyProperties(value, queueStatInfo);
return queueStatInfo;
}
public String getClientInfo() {
return clientInfo;
}
public void setClientInfo(String clientInfo) {
this.clientInfo = clientInfo;
}
public String getBrokerName() {
return brokerName;
}
public void setBrokerName(String brokerName) {
this.brokerName = brokerName;
}
public int getQueueId() {
return queueId;
}
public void setQueueId(int queueId) {
this.queueId = queueId;
}
public long getBrokerOffset() {
return brokerOffset;
}
public void setBrokerOffset(long brokerOffset) {
this.brokerOffset = brokerOffset;
}
public long getConsumerOffset() {
return consumerOffset;
}
public void setConsumerOffset(long consumerOffset) {
this.consumerOffset = consumerOffset;
}
public long getLastTimestamp() {
return lastTimestamp;
}
public void setLastTimestamp(long lastTimestamp) {
this.lastTimestamp = lastTimestamp;
}
}

62
src/main/java/org/apache/rocketmq/dashboard/model/TopicConsumerInfo.java

@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import com.google.common.collect.Lists;
import java.util.List;
public class TopicConsumerInfo {
private String topic;
private long diffTotal;
private long lastTimestamp;
private List<QueueStatInfo> queueStatInfoList = Lists.newArrayList();
public TopicConsumerInfo(String topic) {
this.topic = topic;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public long getDiffTotal() {
return diffTotal;
}
public void setDiffTotal(long diffTotal) {
this.diffTotal = diffTotal;
}
public List<QueueStatInfo> getQueueStatInfoList() {
return queueStatInfoList;
}
public long getLastTimestamp() {
return lastTimestamp;
}
public void appendQueueStatInfo(QueueStatInfo queueStatInfo) {
queueStatInfoList.add(queueStatInfo);
diffTotal = diffTotal + (queueStatInfo.getBrokerOffset() - queueStatInfo.getConsumerOffset());
lastTimestamp = Math.max(lastTimestamp, queueStatInfo.getLastTimestamp());
}
}

83
src/main/java/org/apache/rocketmq/dashboard/model/User.java

@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import org.hibernate.validator.constraints.Range;
public class User {
public static final int ORDINARY = 0;
public static final int ADMIN = 1;
private long id;
private String name;
private String password;
@Range(min = 0, max = 1)
private int type = 0;
public User(String name, String password, int type) {
this.name = name;
this.password = password;
this.type = type;
}
public User cloneOne() {
return new User(this.name, this.password, this.type);
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
", type=" + type +
'}';
}
}

67
src/main/java/org/apache/rocketmq/dashboard/model/UserInfo.java

@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
public class UserInfo {
public static final String USER_INFO = "userInfo";
private User user;
private long loginTime;
private String ip;
private String sessionId;
public long getLoginTime() {
return loginTime;
}
public void setLoginTime(long loginTime) {
this.loginTime = loginTime;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
@Override
public String toString() {
return "UserInfo{" +
"user=" + user +
", loginTime=" + loginTime +
", ip='" + ip + '\'' +
", sessionId='" + sessionId + '\'' +
'}';
}
}

61
src/main/java/org/apache/rocketmq/dashboard/model/request/ConsumerConfigInfo.java

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.request;
import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
import java.util.List;
public class ConsumerConfigInfo {
private List<String> clusterNameList;
private List<String> brokerNameList;
private SubscriptionGroupConfig subscriptionGroupConfig;
public ConsumerConfigInfo() {
}
public ConsumerConfigInfo(List<String> brokerNameList, SubscriptionGroupConfig subscriptionGroupConfig) {
this.brokerNameList = brokerNameList;
this.subscriptionGroupConfig = subscriptionGroupConfig;
}
public List<String> getClusterNameList() {
return clusterNameList;
}
public void setClusterNameList(List<String> clusterNameList) {
this.clusterNameList = clusterNameList;
}
public List<String> getBrokerNameList() {
return brokerNameList;
}
public void setBrokerNameList(List<String> brokerNameList) {
this.brokerNameList = brokerNameList;
}
public SubscriptionGroupConfig getSubscriptionGroupConfig() {
return subscriptionGroupConfig;
}
public void setSubscriptionGroupConfig(SubscriptionGroupConfig subscriptionGroupConfig) {
this.subscriptionGroupConfig = subscriptionGroupConfig;
}
}

40
src/main/java/org/apache/rocketmq/dashboard/model/request/DeleteSubGroupRequest.java

@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.request;
import java.util.List;
public class DeleteSubGroupRequest {
private String groupName;
private List<String> brokerNameList;
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public List<String> getBrokerNameList() {
return brokerNameList;
}
public void setBrokerNameList(List<String> brokerNameList) {
this.brokerNameList = brokerNameList;
}
}

82
src/main/java/org/apache/rocketmq/dashboard/model/request/MessageQuery.java

@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.request;
public class MessageQuery {
/**
* current page num
*/
private int pageNum;
private int pageSize;
private String topic;
private String taskId;
private long begin;
private long end;
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public long getBegin() {
return begin;
}
public void setBegin(long begin) {
this.begin = begin;
}
public long getEnd() {
return end;
}
public void setEnd(long end) {
this.end = end;
}
}

58
src/main/java/org/apache/rocketmq/dashboard/model/request/ResetOffsetRequest.java

@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.request;
import java.util.List;
public class ResetOffsetRequest {
private List<String> consumerGroupList;
private String topic;
private long resetTime;
private boolean force;
public List<String> getConsumerGroupList() {
return consumerGroupList;
}
public void setConsumerGroupList(List<String> consumerGroupList) {
this.consumerGroupList = consumerGroupList;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public long getResetTime() {
return resetTime;
}
public void setResetTime(long resetTime) {
this.resetTime = resetTime;
}
public boolean isForce() {
return force;
}
public void setForce(boolean force) {
this.force = force;
}
}

28
src/main/java/org/apache/rocketmq/dashboard/model/request/SendTopicMessageRequest.java

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.request;
import lombok.Data;
@Data
public class SendTopicMessageRequest {
private String topic;
private String key;
private String tag;
private String messageBody;
private boolean traceEnabled;
}

114
src/main/java/org/apache/rocketmq/dashboard/model/request/TopicConfigInfo.java

@ -0,0 +1,114 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.request;
import com.google.common.base.Objects;
import java.util.List;
public class TopicConfigInfo {
private List<String> clusterNameList;
private List<String> brokerNameList;
/** topicConfig */
private String topicName;
private int writeQueueNums;
private int readQueueNums;
private int perm;
private boolean order;
public List<String> getClusterNameList() {
return clusterNameList;
}
public void setClusterNameList(List<String> clusterNameList) {
this.clusterNameList = clusterNameList;
}
/** topicConfig */
public List<String> getBrokerNameList() {
return brokerNameList;
}
public void setBrokerNameList(List<String> brokerNameList) {
this.brokerNameList = brokerNameList;
}
public String getTopicName() {
return topicName;
}
public void setTopicName(String topicName) {
this.topicName = topicName;
}
public int getWriteQueueNums() {
return writeQueueNums;
}
public void setWriteQueueNums(int writeQueueNums) {
this.writeQueueNums = writeQueueNums;
}
public int getReadQueueNums() {
return readQueueNums;
}
public void setReadQueueNums(int readQueueNums) {
this.readQueueNums = readQueueNums;
}
public int getPerm() {
return perm;
}
public void setPerm(int perm) {
this.perm = perm;
}
public boolean isOrder() {
return order;
}
public void setOrder(boolean order) {
this.order = order;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
TopicConfigInfo that = (TopicConfigInfo) o;
return writeQueueNums == that.writeQueueNums &&
readQueueNums == that.readQueueNums &&
perm == that.perm &&
order == that.order &&
Objects.equal(topicName, that.topicName);
}
@Override
public int hashCode() {
return Objects.hashCode(topicName, writeQueueNums, readQueueNums, perm, order);
}
}

31
src/main/java/org/apache/rocketmq/dashboard/model/trace/MessageTraceGraph.java

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.trace;
import lombok.Data;
import org.apache.rocketmq.dashboard.model.MessageTraceView;
import java.util.List;
@Data
public class MessageTraceGraph {
private ProducerNode producerNode;
private List<SubscriptionNode> subscriptionNodeList;
private List<MessageTraceView> messageTraceViews;
}

32
src/main/java/org/apache/rocketmq/dashboard/model/trace/MessageTraceStatusEnum.java

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.trace;
import lombok.Getter;
@Getter
public enum MessageTraceStatusEnum {
SUCCESS("success"),
FAILED("failed"),
UNKNOWN("unknown");
private final String status;
MessageTraceStatusEnum(String status) {
this.status = status;
}
}

33
src/main/java/org/apache/rocketmq/dashboard/model/trace/ProducerNode.java

@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.trace;
import lombok.Data;
import java.util.List;
@Data
public class ProducerNode {
private String msgId;
private String tags;
private String keys;
private String offSetMsgId;
private String topic;
private String groupName;
private TraceNode traceNode;
private List<TraceNode> transactionNodeList;
}

27
src/main/java/org/apache/rocketmq/dashboard/model/trace/SubscriptionNode.java

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.trace;
import lombok.Data;
import java.util.List;
@Data
public class SubscriptionNode {
private String subscriptionGroup;
private List<TraceNode> consumeNodeList;
}

36
src/main/java/org/apache/rocketmq/dashboard/model/trace/TraceNode.java

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.trace;
import lombok.Data;
@Data
public class TraceNode {
private String requestId;
private String storeHost;
private String clientHost;
private int costTime;
private long beginTimestamp;
private long endTimestamp;
private int retryTimes;
private String status;
private String transactionState;
private String transactionId;
private boolean fromTransactionCheck;
private String msgType;
}

27
src/main/java/org/apache/rocketmq/dashboard/permisssion/Permission.java

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.permisssion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
}

69
src/main/java/org/apache/rocketmq/dashboard/permisssion/PermissionAspect.java

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.permisssion;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.exception.ServiceException;
import org.apache.rocketmq.dashboard.model.UserInfo;
import org.apache.rocketmq.dashboard.service.PermissionService;
import org.apache.rocketmq.dashboard.util.WebUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Aspect
@Component
public class PermissionAspect {
@Resource
private RMQConfigure configure;
@Resource
private PermissionService permissionService;
/**
* @Permission can be applied to the Controller class to implement Permission verification on all methods in the class
* can also be applied to methods in a class for fine control
*/
@Pointcut("@annotation(org.apache.rocketmq.dashboard.permisssion.Permission) || @within(org.apache.rocketmq.dashboard.permisssion.Permission)")
private void permission() {
}
@Around("permission()")
public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable {
if (configure.isLoginRequired()) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String url = request.getRequestURI();
UserInfo userInfo = (UserInfo) request.getSession().getAttribute(WebUtil.USER_INFO);
if (userInfo == null || userInfo.getUser() == null) {
throw new ServiceException(-1, "user not login");
}
boolean checkResult = permissionService.checkUrlAvailable(userInfo, url);
if (!checkResult) {
throw new ServiceException(-1, "no permission");
}
}
return joinPoint.proceed();
}
}

38
src/main/java/org/apache/rocketmq/dashboard/permisssion/UserRoleEnum.java

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.permisssion;
public enum UserRoleEnum {
ADMIN(1, "admin"),
ORDINARY(0, "ordinary");
private int roleType;
private String roleName;
UserRoleEnum(int roleType, String roleName) {
this.roleType = roleType;
this.roleName = roleName;
}
public int getRoleType() {
return roleType;
}
public String getRoleName() {
return roleName;
}
}

49
src/main/java/org/apache/rocketmq/dashboard/service/AbstractCommonService.java

@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import com.google.common.base.Throwables;
import com.google.common.collect.Sets;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
public abstract class AbstractCommonService {
@Resource
protected MQAdminExt mqAdminExt;
protected final Set<String> changeToBrokerNameSet(HashMap<String, Set<String>> clusterAddrTable,
List<String> clusterNameList, List<String> brokerNameList) {
Set<String> finalBrokerNameList = Sets.newHashSet();
if (CollectionUtils.isNotEmpty(clusterNameList)) {
try {
for (String clusterName : clusterNameList) {
finalBrokerNameList.addAll(clusterAddrTable.get(clusterName));
}
}
catch (Exception e) {
throw Throwables.propagate(e);
}
}
if (CollectionUtils.isNotEmpty(brokerNameList)) {
finalBrokerNameList.addAll(brokerNameList);
}
return finalBrokerNameList;
}
}

27
src/main/java/org/apache/rocketmq/dashboard/service/ClusterService.java

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import java.util.Map;
import java.util.Properties;
public interface ClusterService {
Map<String, Object> list();
Properties getBrokerConfig(String brokerAddr);
}

32
src/main/java/org/apache/rocketmq/dashboard/service/ConfigService.java

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import java.util.Map;
public interface ConfigService {
Map<String, String> queryConfigMap();
boolean createConfig(String name, String value);
boolean updateConfig(String name, String value);
boolean deleteConfig(String name, String value);
}

58
src/main/java/org/apache/rocketmq/dashboard/service/ConsumerService.java

@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.common.protocol.body.ConsumerConnection;
import org.apache.rocketmq.common.protocol.body.ConsumerRunningInfo;
import org.apache.rocketmq.dashboard.model.ConsumerGroupRollBackStat;
import org.apache.rocketmq.dashboard.model.GroupConsumeInfo;
import org.apache.rocketmq.dashboard.model.TopicConsumerInfo;
import org.apache.rocketmq.dashboard.model.request.ConsumerConfigInfo;
import org.apache.rocketmq.dashboard.model.request.DeleteSubGroupRequest;
import org.apache.rocketmq.dashboard.model.request.ResetOffsetRequest;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface ConsumerService {
List<GroupConsumeInfo> queryGroupList();
GroupConsumeInfo queryGroup(String consumerGroup);
List<TopicConsumerInfo> queryConsumeStatsListByGroupName(String groupName);
List<TopicConsumerInfo> queryConsumeStatsList(String topic, String groupName);
Map<String, TopicConsumerInfo> queryConsumeStatsListByTopicName(String topic);
Map<String /*consumerGroup*/, ConsumerGroupRollBackStat> resetOffset(ResetOffsetRequest resetOffsetRequest);
List<ConsumerConfigInfo> examineSubscriptionGroupConfig(String group);
boolean deleteSubGroup(DeleteSubGroupRequest deleteSubGroupRequest);
boolean createAndUpdateSubscriptionGroupConfig(ConsumerConfigInfo consumerConfigInfo);
Set<String> fetchBrokerNameSetBySubscriptionGroup(String group);
ConsumerConnection getConsumerConnection(String consumerGroup);
ConsumerRunningInfo getConsumerRunningInfo(String consumerGroup, String clientId, boolean jstack);
}

36
src/main/java/org/apache/rocketmq/dashboard/service/DashboardCollectService.java

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import com.google.common.cache.LoadingCache;
import java.io.File;
import java.util.List;
import java.util.Map;
public interface DashboardCollectService {
// todo just move the task to org.apache.rocketmq.dashboard.task.DashboardCollectTask
// the code can be reconstruct
LoadingCache<String, List<String>> getBrokerMap();
LoadingCache<String, List<String>> getTopicMap();
Map<String, List<String>> jsonDataFile2map(File file);
Map<String, List<String>> getBrokerCache(String date);
Map<String, List<String>> getTopicCache(String date);
}

42
src/main/java/org/apache/rocketmq/dashboard/service/DashboardService.java

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import java.util.List;
import java.util.Map;
public interface DashboardService {
/**
* @param date format yyyy-MM-dd
*/
Map<String, List<String>> queryBrokerData(String date);
/**
* @param date format yyyy-MM-dd
*/
Map<String, List<String>> queryTopicData(String date);
/**
* @param date format yyyy-MM-dd
* @param topicName
*/
List<String> queryTopicData(String date, String topicName);
List<String> queryTopicCurrentData();
}

25
src/main/java/org/apache/rocketmq/dashboard/service/LoginService.java

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface LoginService {
boolean login(HttpServletRequest request, HttpServletResponse response);
}

59
src/main/java/org/apache/rocketmq/dashboard/service/MessageService.java

@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.common.Pair;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.dashboard.model.MessagePage;
import org.apache.rocketmq.dashboard.model.request.MessageQuery;
import org.apache.rocketmq.tools.admin.api.MessageTrack;
import org.apache.rocketmq.dashboard.model.MessageView;
import java.util.List;
public interface MessageService {
/**
* @param subject
* @param msgId
*/
Pair<MessageView, List<MessageTrack>> viewMessage(String subject, final String msgId);
List<MessageView> queryMessageByTopicAndKey(final String topic, final String key);
/**
* @param topic
* @param begin
* @param end
* org.apache.rocketmq.tools.command.message.PrintMessageSubCommand
*/
List<MessageView> queryMessageByTopic(final String topic, final long begin,
final long end);
List<MessageTrack> messageTrackDetail(MessageExt msg);
ConsumeMessageDirectlyResult consumeMessageDirectly(String topic, String msgId, String consumerGroup,
String clientId);
MessagePage queryMessageByPage(MessageQuery query);
}

31
src/main/java/org/apache/rocketmq/dashboard/service/MessageTraceService.java

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import java.util.List;
import org.apache.rocketmq.dashboard.model.MessageTraceView;
import org.apache.rocketmq.dashboard.model.trace.MessageTraceGraph;
public interface MessageTraceService {
List<MessageTraceView> queryMessageTraceKey(final String key);
List<MessageTraceView> queryMessageTraceByTopicAndKey(final String topic, final String key);
MessageTraceGraph queryMessageTraceGraph(final String key, final String traceTopic);
}

30
src/main/java/org/apache/rocketmq/dashboard/service/MonitorService.java

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import java.util.Map;
import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig;
public interface MonitorService {
boolean createOrUpdateConsumerMonitor(String name, ConsumerMonitorConfig config);
Map<String, ConsumerMonitorConfig> queryConsumerMonitorConfig();
ConsumerMonitorConfig queryConsumerMonitorConfigByGroupName(String consumeGroupName);
boolean deleteConsumerMonitor(String consumeGroupName);
}

34
src/main/java/org/apache/rocketmq/dashboard/service/OpsService.java

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import java.util.Map;
import org.apache.rocketmq.dashboard.service.checker.CheckerType;
public interface OpsService {
Map<String, Object> homePageInfo();
void updateNameSvrAddrList(String nameSvrAddrList);
String getNameSvrList();
Map<CheckerType,Object> rocketMqStatusCheck();
boolean updateIsVIPChannel(String useVIPChannel);
boolean updateUseTLS(boolean useTLS);
}

24
src/main/java/org/apache/rocketmq/dashboard/service/PermissionService.java

@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.dashboard.model.UserInfo;
public interface PermissionService {
boolean checkUrlAvailable(UserInfo userInfo, String url);
}

24
src/main/java/org/apache/rocketmq/dashboard/service/ProducerService.java

@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.common.protocol.body.ProducerConnection;
public interface ProducerService {
ProducerConnection getProducerConnection(String producerGroup, String topic);
}

54
src/main/java/org/apache/rocketmq/dashboard/service/TopicService.java

@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.admin.TopicStatsTable;
import org.apache.rocketmq.common.protocol.body.GroupList;
import org.apache.rocketmq.common.protocol.body.TopicList;
import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.dashboard.model.request.SendTopicMessageRequest;
import org.apache.rocketmq.dashboard.model.request.TopicConfigInfo;
import java.util.List;
public interface TopicService {
TopicList fetchAllTopicList(boolean skipSysProcess, boolean skipRetryAndDlq);
TopicStatsTable stats(String topic);
TopicRouteData route(String topic);
GroupList queryTopicConsumerInfo(String topic);
void createOrUpdate(TopicConfigInfo topicCreateOrUpdateRequest);
TopicConfig examineTopicConfig(String topic, String brokerName);
List<TopicConfigInfo> examineTopicConfig(String topic);
boolean deleteTopic(String topic, String clusterName);
boolean deleteTopic(String topic);
boolean deleteTopicInBroker(String brokerName, String topic);
SendResult sendTopicMessageRequest(SendTopicMessageRequest sendTopicMessageRequest);
}

25
src/main/java/org/apache/rocketmq/dashboard/service/UserService.java

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.dashboard.model.User;
public interface UserService {
User queryByName(String name);
User queryByUsernameAndPassword(String username, String password);
}

23
src/main/java/org/apache/rocketmq/dashboard/service/checker/CheckerType.java

@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.checker;
public enum CheckerType {
CLUSTER_HEALTH_CHECK,
TOPIC_ONLY_ONE_BROKER_CHECK
}

24
src/main/java/org/apache/rocketmq/dashboard/service/checker/RocketMqChecker.java

@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.checker;
public interface RocketMqChecker {
public Object doCheck();
public CheckerType checkerType();
}

34
src/main/java/org/apache/rocketmq/dashboard/service/checker/impl/ClusterHealthCheckerImpl.java

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.checker.impl;
import org.apache.rocketmq.dashboard.service.checker.CheckerType;
import org.apache.rocketmq.dashboard.service.checker.RocketMqChecker;
import org.springframework.stereotype.Service;
@Service
public class ClusterHealthCheckerImpl implements RocketMqChecker {
@Override
public Object doCheck() {
return null;
}
@Override
public CheckerType checkerType() {
return CheckerType.CLUSTER_HEALTH_CHECK;
}
}

39
src/main/java/org/apache/rocketmq/dashboard/service/checker/impl/TopicOnlyOneBrokerCheckerImpl.java

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.checker.impl;
import org.apache.rocketmq.dashboard.service.checker.CheckerType;
import org.apache.rocketmq.dashboard.service.checker.RocketMqChecker;
import org.springframework.stereotype.Service;
/**
* TODO
* here the checkers is not implemented yet
*/
@Service
public class TopicOnlyOneBrokerCheckerImpl implements RocketMqChecker {
@Override
public Object doCheck() {
return null;
}
@Override
public CheckerType checkerType() {
return CheckerType.TOPIC_ONLY_ONE_BROKER_CHECK;
}
}

551
src/main/java/org/apache/rocketmq/dashboard/service/client/MQAdminExtImpl.java

@ -0,0 +1,551 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.client;
import com.google.common.base.Throwables;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.rocketmq.client.QueryResult;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.MQAdminImpl;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.admin.ConsumeStats;
import org.apache.rocketmq.common.admin.RollbackStats;
import org.apache.rocketmq.common.admin.TopicStatsTable;
import org.apache.rocketmq.common.message.MessageClientIDSetter;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.ResponseCode;
import org.apache.rocketmq.common.protocol.body.BrokerStatsData;
import org.apache.rocketmq.common.protocol.body.ClusterAclVersionInfo;
import org.apache.rocketmq.common.protocol.body.ClusterInfo;
import org.apache.rocketmq.common.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.common.protocol.body.ConsumeStatsList;
import org.apache.rocketmq.common.protocol.body.ConsumerConnection;
import org.apache.rocketmq.common.protocol.body.ConsumerRunningInfo;
import org.apache.rocketmq.common.protocol.body.GroupList;
import org.apache.rocketmq.common.protocol.body.KVTable;
import org.apache.rocketmq.common.protocol.body.ProducerConnection;
import org.apache.rocketmq.common.protocol.body.QueryConsumeQueueResponseBody;
import org.apache.rocketmq.common.protocol.body.QueueTimeSpan;
import org.apache.rocketmq.common.protocol.body.SubscriptionGroupWrapper;
import org.apache.rocketmq.common.protocol.body.TopicConfigSerializeWrapper;
import org.apache.rocketmq.common.protocol.body.TopicList;
import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.remoting.RemotingClient;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.exception.RemotingConnectException;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.apache.rocketmq.tools.admin.api.MessageTrack;
import org.joor.Reflect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import static org.apache.rocketmq.remoting.protocol.RemotingSerializable.decode;
@Service
public class MQAdminExtImpl implements MQAdminExt {
private Logger logger = LoggerFactory.getLogger(MQAdminExtImpl.class);
public MQAdminExtImpl() {
}
@Override
public void updateBrokerConfig(String brokerAddr, Properties properties)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
UnsupportedEncodingException, InterruptedException, MQBrokerException {
MQAdminInstance.threadLocalMQAdminExt().updateBrokerConfig(brokerAddr, properties);
}
@Override
public void createAndUpdateTopicConfig(String addr, TopicConfig config)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().createAndUpdateTopicConfig(addr, config);
}
@Override public void createAndUpdatePlainAccessConfig(String addr,
PlainAccessConfig plainAccessConfig) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
}
@Override public void deletePlainAccessConfig(String addr,
String accessKey) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
}
@Override public void updateGlobalWhiteAddrConfig(String addr,
String globalWhiteAddrs) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
}
@Override public ClusterAclVersionInfo examineBrokerClusterAclVersionInfo(
String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return null;
}
@Override public AclConfig examineBrokerClusterAclConfig(
String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return null;
}
@Override
public void createAndUpdateSubscriptionGroupConfig(String addr, SubscriptionGroupConfig config)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().createAndUpdateSubscriptionGroupConfig(addr, config);
}
@Override
public SubscriptionGroupConfig examineSubscriptionGroupConfig(String addr, String group) {
RemotingClient remotingClient = MQAdminInstance.threadLocalRemotingClient();
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_SUBSCRIPTIONGROUP_CONFIG, null);
RemotingCommand response = null;
try {
response = remotingClient.invokeSync(addr, request, 3000);
}
catch (Exception err) {
throw Throwables.propagate(err);
}
assert response != null;
switch (response.getCode()) {
case ResponseCode.SUCCESS: {
SubscriptionGroupWrapper subscriptionGroupWrapper = decode(response.getBody(), SubscriptionGroupWrapper.class);
return subscriptionGroupWrapper.getSubscriptionGroupTable().get(group);
}
default:
throw Throwables.propagate(new MQBrokerException(response.getCode(), response.getRemark()));
}
}
@Override
public TopicConfig examineTopicConfig(String addr, String topic) {
RemotingClient remotingClient = MQAdminInstance.threadLocalRemotingClient();
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_TOPIC_CONFIG, null);
RemotingCommand response = null;
try {
response = remotingClient.invokeSync(addr, request, 3000);
}
catch (Exception err) {
throw Throwables.propagate(err);
}
switch (response.getCode()) {
case ResponseCode.SUCCESS: {
TopicConfigSerializeWrapper topicConfigSerializeWrapper = decode(response.getBody(), TopicConfigSerializeWrapper.class);
return topicConfigSerializeWrapper.getTopicConfigTable().get(topic);
}
default:
throw Throwables.propagate(new MQBrokerException(response.getCode(), response.getRemark()));
}
}
@Override
public TopicStatsTable examineTopicStats(String topic)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().examineTopicStats(topic);
}
@Override
public TopicList fetchAllTopicList() throws RemotingException, MQClientException, InterruptedException {
TopicList topicList = MQAdminInstance.threadLocalMQAdminExt().fetchAllTopicList();
logger.debug("op=look={}", JsonUtil.obj2String(topicList.getTopicList()));
return topicList;
}
@Override
public KVTable fetchBrokerRuntimeStats(String brokerAddr)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().fetchBrokerRuntimeStats(brokerAddr);
}
@Override
public ConsumeStats examineConsumeStats(String consumerGroup)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().examineConsumeStats(consumerGroup);
}
@Override
public ConsumeStats examineConsumeStats(String consumerGroup, String topic)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().examineConsumeStats(consumerGroup, topic);
}
@Override
public ClusterInfo examineBrokerClusterInfo()
throws InterruptedException, MQBrokerException, RemotingTimeoutException, RemotingSendRequestException,
RemotingConnectException {
return MQAdminInstance.threadLocalMQAdminExt().examineBrokerClusterInfo();
}
@Override
public TopicRouteData examineTopicRouteInfo(String topic)
throws RemotingException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().examineTopicRouteInfo(topic);
}
@Override
public ConsumerConnection examineConsumerConnectionInfo(String consumerGroup)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
InterruptedException, MQBrokerException, RemotingException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().examineConsumerConnectionInfo(consumerGroup);
}
@Override
public ProducerConnection examineProducerConnectionInfo(String producerGroup, String topic)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().examineProducerConnectionInfo(producerGroup, topic);
}
@Override
public List<String> getNameServerAddressList() {
return MQAdminInstance.threadLocalMQAdminExt().getNameServerAddressList();
}
@Override
public int wipeWritePermOfBroker(String namesrvAddr, String brokerName)
throws RemotingCommandException, RemotingConnectException, RemotingSendRequestException,
RemotingTimeoutException, InterruptedException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().wipeWritePermOfBroker(namesrvAddr, brokerName);
}
@Override
public void putKVConfig(String namespace, String key, String value) {
MQAdminInstance.threadLocalMQAdminExt().putKVConfig(namespace, key, value);
}
@Override
public String getKVConfig(String namespace, String key)
throws RemotingException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().getKVConfig(namespace, key);
}
@Override
public KVTable getKVListByNamespace(String namespace)
throws RemotingException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().getKVListByNamespace(namespace);
}
@Override
public void deleteTopicInBroker(Set<String> addrs, String topic)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
logger.info("addrs={} topic={}", JsonUtil.obj2String(addrs), topic);
MQAdminInstance.threadLocalMQAdminExt().deleteTopicInBroker(addrs, topic);
}
@Override
public void deleteTopicInNameServer(Set<String> addrs, String topic)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().deleteTopicInNameServer(addrs, topic);
}
@Override
public void deleteSubscriptionGroup(String addr, String groupName)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().deleteSubscriptionGroup(addr, groupName);
}
@Override
public void deleteSubscriptionGroup(String addr, String groupName, boolean removeOffset) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
throw new UnsupportedOperationException();
}
@Override
public void createAndUpdateKvConfig(String namespace, String key, String value)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().createAndUpdateKvConfig(namespace, key, value);
}
@Override
public void deleteKvConfig(String namespace, String key)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().deleteKvConfig(namespace, key);
}
@Override
public List<RollbackStats> resetOffsetByTimestampOld(String consumerGroup, String topic, long timestamp,
boolean force) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().resetOffsetByTimestampOld(consumerGroup, topic, timestamp, force);
}
@Override
public Map<MessageQueue, Long> resetOffsetByTimestamp(String topic, String group, long timestamp,
boolean isForce) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().resetOffsetByTimestamp(topic, group, timestamp, isForce);
}
@Override
public void resetOffsetNew(String consumerGroup, String topic, long timestamp)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().resetOffsetNew(consumerGroup, topic, timestamp);
}
@Override
public Map<String, Map<MessageQueue, Long>> getConsumeStatus(String topic, String group,
String clientAddr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().getConsumeStatus(topic, group, clientAddr);
}
@Override
public void createOrUpdateOrderConf(String key, String value, boolean isCluster)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().createOrUpdateOrderConf(key, value, isCluster);
}
@Override
public GroupList queryTopicConsumeByWho(String topic)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
InterruptedException, MQBrokerException, RemotingException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().queryTopicConsumeByWho(topic);
}
@Override
public boolean cleanExpiredConsumerQueue(String cluster)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException,
InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().cleanExpiredConsumerQueue(cluster);
}
@Override
public boolean cleanExpiredConsumerQueueByAddr(String addr)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException,
InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().cleanExpiredConsumerQueueByAddr(addr);
}
@Override
public ConsumerRunningInfo getConsumerRunningInfo(String consumerGroup, String clientId, boolean jstack)
throws RemotingException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().getConsumerRunningInfo(consumerGroup, clientId, jstack);
}
@Override
public ConsumeMessageDirectlyResult consumeMessageDirectly(String consumerGroup, String clientId,
String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().consumeMessageDirectly(consumerGroup, clientId, msgId);
}
@Override
public List<MessageTrack> messageTrackDetail(MessageExt msg)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().messageTrackDetail(msg);
}
@Override
public void cloneGroupOffset(String srcGroup, String destGroup, String topic, boolean isOffline)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
MQAdminInstance.threadLocalMQAdminExt().cloneGroupOffset(srcGroup, destGroup, topic, isOffline);
}
@Override
public void createTopic(String key, String newTopic, int queueNum) throws MQClientException {
MQAdminInstance.threadLocalMQAdminExt().createTopic(key, newTopic, queueNum);
}
@Override
public void createTopic(String key, String newTopic, int queueNum, int topicSysFlag)
throws MQClientException {
MQAdminInstance.threadLocalMQAdminExt().createTopic(key, newTopic, queueNum, topicSysFlag);
}
@Override
public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().searchOffset(mq, timestamp);
}
@Override
public long maxOffset(MessageQueue mq) throws MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().maxOffset(mq);
}
@Override
public long minOffset(MessageQueue mq) throws MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().minOffset(mq);
}
@Override
public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().earliestMsgStoreTime(mq);
}
@Override
public MessageExt viewMessage(String msgId)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().viewMessage(msgId);
}
@Override
public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end)
throws MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().queryMessage(topic, key, maxNum, begin, end);
}
@Override
@Deprecated
public void start() throws MQClientException {
throw new IllegalStateException("thisMethod is deprecated.use org.apache.rocketmq.dashboard.aspect.admin.MQAdminAspect instead of this");
}
@Override
@Deprecated
public void shutdown() {
throw new IllegalStateException("thisMethod is deprecated.use org.apache.rocketmq.dashboard.aspect.admin.MQAdminAspect instead of this");
}
// below is 3.2.6->3.5.8 updated
@Override
public List<QueueTimeSpan> queryConsumeTimeSpan(String topic,
String group) throws InterruptedException, MQBrokerException, RemotingException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().queryConsumeTimeSpan(topic, group);
}
//MessageClientIDSetter.getNearlyTimeFromID has bug,so we subtract half a day
//next version we will remove it
//https://issues.apache.org/jira/browse/ROCKETMQ-111
//https://github.com/apache/incubator-rocketmq/pull/69
@Override
public MessageExt viewMessage(String topic,
String msgId) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
logger.info("MessageClientIDSetter.getNearlyTimeFromID(msgId)={} msgId={}", MessageClientIDSetter.getNearlyTimeFromID(msgId), msgId);
try {
return viewMessage(msgId);
}
catch (Exception e) {
}
MQAdminImpl mqAdminImpl = MQAdminInstance.threadLocalMqClientInstance().getMQAdminImpl();
QueryResult qr = Reflect.on(mqAdminImpl).call("queryMessage", topic, msgId, 32,
MessageClientIDSetter.getNearlyTimeFromID(msgId).getTime() - 1000 * 60 * 60 * 13L, Long.MAX_VALUE, true).get();
if (qr != null && qr.getMessageList() != null && qr.getMessageList().size() > 0) {
return qr.getMessageList().get(0);
}
else {
return null;
}
}
@Override
public ConsumeMessageDirectlyResult consumeMessageDirectly(String consumerGroup, String clientId, String topic,
String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().consumeMessageDirectly(consumerGroup, clientId, topic, msgId);
}
@Override
public Properties getBrokerConfig(
String brokerAddr) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, UnsupportedEncodingException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().getBrokerConfig(brokerAddr);
}
@Override
public TopicList fetchTopicsByCLuster(
String clusterName) throws RemotingException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().fetchTopicsByCLuster(clusterName);
}
@Override
public boolean cleanUnusedTopic(
String cluster) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().cleanUnusedTopic(cluster);
}
@Override
public boolean cleanUnusedTopicByAddr(
String addr) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().cleanUnusedTopicByAddr(addr);
}
@Override
public BrokerStatsData viewBrokerStatsData(String brokerAddr, String statsName,
String statsKey) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().viewBrokerStatsData(brokerAddr, statsName, statsKey);
}
@Override
public Set<String> getClusterList(
String topic) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().getClusterList(topic);
}
@Override
public ConsumeStatsList fetchConsumeStatsInBroker(String brokerAddr, boolean isOrder,
long timeoutMillis) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().fetchConsumeStatsInBroker(brokerAddr, isOrder, timeoutMillis);
}
@Override
public Set<String> getTopicClusterList(
String topic) throws InterruptedException, MQBrokerException, MQClientException, RemotingException {
return MQAdminInstance.threadLocalMQAdminExt().getTopicClusterList(topic);
}
@Override
public SubscriptionGroupWrapper getAllSubscriptionGroup(String brokerAddr,
long timeoutMillis) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().getAllSubscriptionGroup(brokerAddr, timeoutMillis);
}
@Override
public TopicConfigSerializeWrapper getAllTopicGroup(String brokerAddr,
long timeoutMillis) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().getAllTopicGroup(brokerAddr, timeoutMillis);
}
@Override
public void updateConsumeOffset(String brokerAddr, String consumeGroup, MessageQueue mq,
long offset) throws RemotingException, InterruptedException, MQBrokerException {
MQAdminInstance.threadLocalMQAdminExt().updateConsumeOffset(brokerAddr, consumeGroup, mq, offset);
}
// 4.0.0 added
@Override public void updateNameServerConfig(Properties properties,
List<String> list) throws InterruptedException, RemotingConnectException, UnsupportedEncodingException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, MQBrokerException {
}
@Override public Map<String, Properties> getNameServerConfig(
List<String> list) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQClientException, UnsupportedEncodingException {
return null;
}
@Override public QueryConsumeQueueResponseBody queryConsumeQueue(String brokerAddr, String topic,
int queueId, long index, int count,
String consumerGroup) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQClientException {
return null;
}
@Override public boolean resumeCheckHalfMessage(
String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return false;
}
@Override public boolean resumeCheckHalfMessage(String topic,
String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return false;
}
}

75
src/main/java/org/apache/rocketmq/dashboard/service/client/MQAdminInstance.java

@ -0,0 +1,75 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.client;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.rocketmq.client.impl.MQClientAPIImpl;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.remoting.RemotingClient;
import org.apache.rocketmq.tools.admin.DefaultMQAdminExtImpl;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.joor.Reflect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MQAdminInstance {
private static final Logger LOGGER = LoggerFactory.getLogger(MQAdminInstance.class);
private static final ThreadLocal<MQAdminExt> MQ_ADMIN_EXT_THREAD_LOCAL = new ThreadLocal<>();
public static MQAdminExt threadLocalMQAdminExt() {
MQAdminExt mqAdminExt = MQ_ADMIN_EXT_THREAD_LOCAL.get();
if (mqAdminExt == null) {
throw new IllegalStateException("defaultMQAdminExt should be init before you get this");
}
return mqAdminExt;
}
public static RemotingClient threadLocalRemotingClient() {
MQClientInstance mqClientInstance = threadLocalMqClientInstance();
MQClientAPIImpl mQClientAPIImpl = Reflect.on(mqClientInstance).get("mQClientAPIImpl");
return Reflect.on(mQClientAPIImpl).get("remotingClient");
}
public static MQClientInstance threadLocalMqClientInstance() {
DefaultMQAdminExtImpl defaultMQAdminExtImpl = Reflect.on(MQAdminInstance.threadLocalMQAdminExt()).get("defaultMQAdminExtImpl");
return Reflect.on(defaultMQAdminExtImpl).get("mqClientInstance");
}
public static void createMQAdmin(GenericObjectPool<MQAdminExt> mqAdminExtPool) {
try {
// Get the mqAdmin instance from the object pool
MQAdminExt mqAdminExt = mqAdminExtPool.borrowObject();
MQ_ADMIN_EXT_THREAD_LOCAL.set(mqAdminExt);
} catch (Exception e) {
LOGGER.error("get mqAdmin from pool error", e);
}
}
public static void returnMQAdmin(GenericObjectPool<MQAdminExt> mqAdminExtPool) {
MQAdminExt mqAdminExt = MQ_ADMIN_EXT_THREAD_LOCAL.get();
if (mqAdminExt != null) {
try {
// After execution, return the mqAdmin instance to the object pool
mqAdminExtPool.returnObject(mqAdminExt);
} catch (Exception e) {
LOGGER.error("return mqAdmin to pool error", e);
}
}
MQ_ADMIN_EXT_THREAD_LOCAL.remove();
}
}

83
src/main/java/org/apache/rocketmq/dashboard/service/impl/AbstractFileStore.java

@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.impl;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.srvutil.FileWatchService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractFileStore {
public final Logger log = LoggerFactory.getLogger(this.getClass());
public String filePath;
public AbstractFileStore(RMQConfigure configure, String fileName) {
filePath = configure.getRocketMqDashboardDataPath() + File.separator + fileName;
if (!new File(filePath).exists()) {
// Use the default path
InputStream inputStream = getClass().getResourceAsStream("/" + fileName);
if (inputStream == null) {
log.error(String.format("Can not found the file %s in Spring Boot jar", fileName));
System.exit(1);
} else {
try {
load(inputStream);
} catch (Exception e) {
log.error("fail to load file {}", filePath, e);
} finally {
try {
inputStream.close();
} catch (IOException e) {
log.error("inputStream close exception", e);
}
}
}
} else {
log.info(String.format("configure file is %s", filePath));
load();
watch();
}
}
abstract void load(InputStream inputStream);
private void load() {
load(null);
}
private boolean watch() {
try {
FileWatchService fileWatchService = new FileWatchService(new String[] {filePath}, new FileWatchService.Listener() {
@Override
public void onChanged(String path) {
log.info("The file changed, reload the context");
load();
}
});
fileWatchService.start();
log.info("Succeed to start FileWatcherService");
return true;
} catch (Exception e) {
log.error("Failed to start FileWatcherService", e);
}
return false;
}
}

76
src/main/java/org/apache/rocketmq/dashboard/service/impl/ClusterServiceImpl.java

@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.impl;
import org.apache.rocketmq.common.protocol.body.ClusterInfo;
import org.apache.rocketmq.common.protocol.body.KVTable;
import org.apache.rocketmq.common.protocol.route.BrokerData;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.apache.rocketmq.dashboard.service.ClusterService;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Properties;
@Service
public class ClusterServiceImpl implements ClusterService {
private Logger logger = LoggerFactory.getLogger(ClusterServiceImpl.class);
@Resource
private MQAdminExt mqAdminExt;
@Override
public Map<String, Object> list() {
try {
Map<String, Object> resultMap = Maps.newHashMap();
ClusterInfo clusterInfo = mqAdminExt.examineBrokerClusterInfo();
logger.info("op=look_clusterInfo {}", JsonUtil.obj2String(clusterInfo));
Map<String/*brokerName*/, Map<Long/* brokerId */, Object/* brokerDetail */>> brokerServer = Maps.newHashMap();
for (BrokerData brokerData : clusterInfo.getBrokerAddrTable().values()) {
Map<Long, Object> brokerMasterSlaveMap = Maps.newHashMap();
for (Map.Entry<Long/* brokerId */, String/* broker address */> brokerAddr : brokerData.getBrokerAddrs().entrySet()) {
KVTable kvTable = mqAdminExt.fetchBrokerRuntimeStats(brokerAddr.getValue());
brokerMasterSlaveMap.put(brokerAddr.getKey(), kvTable.getTable());
}
brokerServer.put(brokerData.getBrokerName(), brokerMasterSlaveMap);
}
resultMap.put("clusterInfo", clusterInfo);
resultMap.put("brokerServer", brokerServer);
return resultMap;
}
catch (Exception err) {
throw Throwables.propagate(err);
}
}
@Override
public Properties getBrokerConfig(String brokerAddr) {
try {
return mqAdminExt.getBrokerConfig(brokerAddr);
}
catch (Exception e) {
throw Throwables.propagate(e);
}
}
}

115
src/main/java/org/apache/rocketmq/dashboard/service/impl/ConfigServiceImpl.java

@ -0,0 +1,115 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.impl;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.service.AbstractCommonService;
import org.apache.rocketmq.dashboard.service.ConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.*;
import java.util.*;
@Service
public class ConfigServiceImpl extends AbstractCommonService implements ConfigService {
private Logger logger = LoggerFactory.getLogger(ConfigServiceImpl.class);
@Autowired
private RMQConfigure rmqConfigure;
@Override
public Map<String, String> queryConfigMap() {
Map<String, String> result = new HashMap<>();
String folderPath = rmqConfigure.getRocketMqDashboardDataPath(); // 读取目录下所有txt文件
File folder = new File(folderPath);
if (folder.exists()) {
File[] files = folder.listFiles();
for (File file : files) {
if (file.isFile() && file.getName().endsWith(".txt")) {
try (BufferedReader reader = new BufferedReader(new FileReader(file.getAbsolutePath()))) {
String line = reader.readLine();
result.put(file.getName().replace(".txt", ""), line);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
} else {
folder.mkdir();
}
return result;
}
@Override
public boolean createConfig(String name, String value) {
String fileName = rmqConfigure.getRocketMqDashboardDataPath() + File.separator + name + ".txt";
File file = new File(fileName);
if(file.exists()) {
logger.error("文件已经存在");
return false;
}
try {
if (file.createNewFile()) {
FileWriter writer = new FileWriter(file);
writer.write(value);
writer.close();
} else {
logger.error("文件无法创建");
return false;
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
return false;
}
return true;
}
@Override
public boolean updateConfig(String name, String value) {
String fileName = rmqConfigure.getRocketMqDashboardDataPath() + File.separator + name + ".txt";
File file = new File(fileName);
if(!file.exists()) {
logger.error("文件不存在");
return false;
}
try {
FileWriter fileWriter = new FileWriter(fileName, false);
fileWriter.write(value);
fileWriter.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
return false;
}
return true;
}
@Override
public boolean deleteConfig(String name, String value) {
String fileName = rmqConfigure.getRocketMqDashboardDataPath() + File.separator + name + ".txt";
File file = new File(fileName);
if(!file.exists()) {
logger.error("文件不存在");
return false;
}
return file.delete();
}
}

332
src/main/java/org/apache/rocketmq/dashboard/service/impl/ConsumerServiceImpl.java

@ -0,0 +1,332 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.common.admin.ConsumeStats;
import org.apache.rocketmq.common.admin.RollbackStats;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.ResponseCode;
import org.apache.rocketmq.common.protocol.body.ClusterInfo;
import org.apache.rocketmq.common.protocol.body.Connection;
import org.apache.rocketmq.common.protocol.body.ConsumerConnection;
import org.apache.rocketmq.common.protocol.body.ConsumerRunningInfo;
import org.apache.rocketmq.common.protocol.body.GroupList;
import org.apache.rocketmq.common.protocol.body.SubscriptionGroupWrapper;
import org.apache.rocketmq.common.protocol.route.BrokerData;
import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
import org.apache.rocketmq.dashboard.model.ConsumerGroupRollBackStat;
import org.apache.rocketmq.dashboard.model.GroupConsumeInfo;
import org.apache.rocketmq.dashboard.model.QueueStatInfo;
import org.apache.rocketmq.dashboard.model.TopicConsumerInfo;
import org.apache.rocketmq.dashboard.model.request.ConsumerConfigInfo;
import org.apache.rocketmq.dashboard.model.request.DeleteSubGroupRequest;
import org.apache.rocketmq.dashboard.model.request.ResetOffsetRequest;
import org.apache.rocketmq.dashboard.service.AbstractCommonService;
import org.apache.rocketmq.dashboard.service.ConsumerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import static com.google.common.base.Throwables.propagate;
@Service
public class ConsumerServiceImpl extends AbstractCommonService implements ConsumerService {
private Logger logger = LoggerFactory.getLogger(ConsumerServiceImpl.class);
@Override
public List<GroupConsumeInfo> queryGroupList() {
Set<String> consumerGroupSet = Sets.newHashSet();
try {
ClusterInfo clusterInfo = mqAdminExt.examineBrokerClusterInfo();
for (BrokerData brokerData : clusterInfo.getBrokerAddrTable().values()) {
SubscriptionGroupWrapper subscriptionGroupWrapper = mqAdminExt.getAllSubscriptionGroup(brokerData.selectBrokerAddr(), 3000L);
consumerGroupSet.addAll(subscriptionGroupWrapper.getSubscriptionGroupTable().keySet());
}
}
catch (Exception err) {
throw Throwables.propagate(err);
}
List<GroupConsumeInfo> groupConsumeInfoList = Lists.newArrayList();
for (String consumerGroup : consumerGroupSet) {
groupConsumeInfoList.add(queryGroup(consumerGroup));
}
Collections.sort(groupConsumeInfoList);
return groupConsumeInfoList;
}
@Override
public GroupConsumeInfo queryGroup(String consumerGroup) {
GroupConsumeInfo groupConsumeInfo = new GroupConsumeInfo();
try {
ConsumeStats consumeStats = null;
try {
consumeStats = mqAdminExt.examineConsumeStats(consumerGroup);
}
catch (Exception e) {
logger.warn("examineConsumeStats exception to consumerGroup {}, response [{}]", consumerGroup, e.getMessage());
}
ConsumerConnection consumerConnection = null;
try {
consumerConnection = mqAdminExt.examineConsumerConnectionInfo(consumerGroup);
}
catch (Exception e) {
logger.warn("examineConsumeStats exception to consumerGroup {}, response [{}]", consumerGroup, e.getMessage());
}
groupConsumeInfo.setGroup(consumerGroup);
if (consumeStats != null) {
groupConsumeInfo.setConsumeTps((int)consumeStats.getConsumeTps());
groupConsumeInfo.setDiffTotal(consumeStats.computeTotalDiff());
}
if (consumerConnection != null) {
groupConsumeInfo.setCount(consumerConnection.getConnectionSet().size());
groupConsumeInfo.setMessageModel(consumerConnection.getMessageModel());
groupConsumeInfo.setConsumeType(consumerConnection.getConsumeType());
groupConsumeInfo.setVersion(MQVersion.getVersionDesc(consumerConnection.computeMinVersion()));
}
}
catch (Exception e) {
logger.warn("examineConsumeStats or examineConsumerConnectionInfo exception, "
+ consumerGroup, e);
}
return groupConsumeInfo;
}
@Override
public List<TopicConsumerInfo> queryConsumeStatsListByGroupName(String groupName) {
return queryConsumeStatsList(null, groupName);
}
@Override
public List<TopicConsumerInfo> queryConsumeStatsList(final String topic, String groupName) {
ConsumeStats consumeStats = null;
try {
consumeStats = mqAdminExt.examineConsumeStats(groupName, topic);
}
catch (Exception e) {
throw propagate(e);
}
List<MessageQueue> mqList = Lists.newArrayList(Iterables.filter(consumeStats.getOffsetTable().keySet(), new Predicate<MessageQueue>() {
@Override
public boolean apply(MessageQueue o) {
return StringUtils.isBlank(topic) || o.getTopic().equals(topic);
}
}));
Collections.sort(mqList);
List<TopicConsumerInfo> topicConsumerInfoList = Lists.newArrayList();
TopicConsumerInfo nowTopicConsumerInfo = null;
Map<MessageQueue, String> messageQueueClientMap = getClientConnection(groupName);
for (MessageQueue mq : mqList) {
if (nowTopicConsumerInfo == null || (!StringUtils.equals(mq.getTopic(), nowTopicConsumerInfo.getTopic()))) {
nowTopicConsumerInfo = new TopicConsumerInfo(mq.getTopic());
topicConsumerInfoList.add(nowTopicConsumerInfo);
}
QueueStatInfo queueStatInfo = QueueStatInfo.fromOffsetTableEntry(mq, consumeStats.getOffsetTable().get(mq));
queueStatInfo.setClientInfo(messageQueueClientMap.get(mq));
nowTopicConsumerInfo.appendQueueStatInfo(queueStatInfo);
}
return topicConsumerInfoList;
}
private Map<MessageQueue, String> getClientConnection(String groupName) {
Map<MessageQueue, String> results = Maps.newHashMap();
try {
ConsumerConnection consumerConnection = mqAdminExt.examineConsumerConnectionInfo(groupName);
for (Connection connection : consumerConnection.getConnectionSet()) {
String clinetId = connection.getClientId();
ConsumerRunningInfo consumerRunningInfo = mqAdminExt.getConsumerRunningInfo(groupName, clinetId, false);
for (MessageQueue messageQueue : consumerRunningInfo.getMqTable().keySet()) {
// results.put(messageQueue, clinetId + " " + connection.getClientAddr());
results.put(messageQueue, clinetId);
}
}
}
catch (Exception err) {
logger.error("op=getClientConnection_error", err);
}
return results;
}
@Override
public Map<String /*groupName*/, TopicConsumerInfo> queryConsumeStatsListByTopicName(String topic) {
Map<String, TopicConsumerInfo> group2ConsumerInfoMap = Maps.newHashMap();
try {
GroupList groupList = mqAdminExt.queryTopicConsumeByWho(topic);
for (String group : groupList.getGroupList()) {
List<TopicConsumerInfo> topicConsumerInfoList = null;
try {
topicConsumerInfoList = queryConsumeStatsList(topic, group);
}
catch (Exception ignore) {
}
group2ConsumerInfoMap.put(group, CollectionUtils.isEmpty(topicConsumerInfoList) ? new TopicConsumerInfo(topic) : topicConsumerInfoList.get(0));
}
return group2ConsumerInfoMap;
}
catch (Exception e) {
throw propagate(e);
}
}
@Override
public Map<String, ConsumerGroupRollBackStat> resetOffset(ResetOffsetRequest resetOffsetRequest) {
Map<String, ConsumerGroupRollBackStat> groupRollbackStats = Maps.newHashMap();
for (String consumerGroup : resetOffsetRequest.getConsumerGroupList()) {
try {
Map<MessageQueue, Long> rollbackStatsMap =
mqAdminExt.resetOffsetByTimestamp(resetOffsetRequest.getTopic(), consumerGroup, resetOffsetRequest.getResetTime(), resetOffsetRequest.isForce());
ConsumerGroupRollBackStat consumerGroupRollBackStat = new ConsumerGroupRollBackStat(true);
List<RollbackStats> rollbackStatsList = consumerGroupRollBackStat.getRollbackStatsList();
for (Map.Entry<MessageQueue, Long> rollbackStatsEntty : rollbackStatsMap.entrySet()) {
RollbackStats rollbackStats = new RollbackStats();
rollbackStats.setRollbackOffset(rollbackStatsEntty.getValue());
rollbackStats.setQueueId(rollbackStatsEntty.getKey().getQueueId());
rollbackStats.setBrokerName(rollbackStatsEntty.getKey().getBrokerName());
rollbackStatsList.add(rollbackStats);
}
groupRollbackStats.put(consumerGroup, consumerGroupRollBackStat);
}
catch (MQClientException e) {
if (ResponseCode.CONSUMER_NOT_ONLINE == e.getResponseCode()) {
try {
ConsumerGroupRollBackStat consumerGroupRollBackStat = new ConsumerGroupRollBackStat(true);
List<RollbackStats> rollbackStatsList = mqAdminExt.resetOffsetByTimestampOld(consumerGroup, resetOffsetRequest.getTopic(), resetOffsetRequest.getResetTime(), true);
consumerGroupRollBackStat.setRollbackStatsList(rollbackStatsList);
groupRollbackStats.put(consumerGroup, consumerGroupRollBackStat);
continue;
}
catch (Exception err) {
logger.error("op=resetOffset_which_not_online_error", err);
}
}
else {
logger.error("op=resetOffset_error", e);
}
groupRollbackStats.put(consumerGroup, new ConsumerGroupRollBackStat(false, e.getMessage()));
}
catch (Exception e) {
logger.error("op=resetOffset_error", e);
groupRollbackStats.put(consumerGroup, new ConsumerGroupRollBackStat(false, e.getMessage()));
}
}
return groupRollbackStats;
}
@Override
public List<ConsumerConfigInfo> examineSubscriptionGroupConfig(String group) {
List<ConsumerConfigInfo> consumerConfigInfoList = Lists.newArrayList();
try {
ClusterInfo clusterInfo = mqAdminExt.examineBrokerClusterInfo();
for (String brokerName : clusterInfo.getBrokerAddrTable().keySet()) { //foreach brokerName
String brokerAddress = clusterInfo.getBrokerAddrTable().get(brokerName).selectBrokerAddr();
SubscriptionGroupConfig subscriptionGroupConfig = mqAdminExt.examineSubscriptionGroupConfig(brokerAddress, group);
if (subscriptionGroupConfig == null) {
continue;
}
consumerConfigInfoList.add(new ConsumerConfigInfo(Lists.newArrayList(brokerName), subscriptionGroupConfig));
}
}
catch (Exception e) {
throw propagate(e);
}
return consumerConfigInfoList;
}
@Override
public boolean deleteSubGroup(DeleteSubGroupRequest deleteSubGroupRequest) {
try {
ClusterInfo clusterInfo = mqAdminExt.examineBrokerClusterInfo();
for (String brokerName : deleteSubGroupRequest.getBrokerNameList()) {
logger.info("addr={} groupName={}", clusterInfo.getBrokerAddrTable().get(brokerName).selectBrokerAddr(), deleteSubGroupRequest.getGroupName());
mqAdminExt.deleteSubscriptionGroup(clusterInfo.getBrokerAddrTable().get(brokerName).selectBrokerAddr(), deleteSubGroupRequest.getGroupName());
}
}
catch (Exception e) {
throw propagate(e);
}
return true;
}
@Override
public boolean createAndUpdateSubscriptionGroupConfig(ConsumerConfigInfo consumerConfigInfo) {
try {
ClusterInfo clusterInfo = mqAdminExt.examineBrokerClusterInfo();
for (String brokerName : changeToBrokerNameSet(clusterInfo.getClusterAddrTable(),
consumerConfigInfo.getClusterNameList(), consumerConfigInfo.getBrokerNameList())) {
mqAdminExt.createAndUpdateSubscriptionGroupConfig(clusterInfo.getBrokerAddrTable().get(brokerName).selectBrokerAddr(), consumerConfigInfo.getSubscriptionGroupConfig());
}
}
catch (Exception err) {
throw Throwables.propagate(err);
}
return true;
}
@Override
public Set<String> fetchBrokerNameSetBySubscriptionGroup(String group) {
Set<String> brokerNameSet = Sets.newHashSet();
try {
List<ConsumerConfigInfo> consumerConfigInfoList = examineSubscriptionGroupConfig(group);
for (ConsumerConfigInfo consumerConfigInfo : consumerConfigInfoList) {
brokerNameSet.addAll(consumerConfigInfo.getBrokerNameList());
}
}
catch (Exception e) {
throw Throwables.propagate(e);
}
return brokerNameSet;
}
@Override
public ConsumerConnection getConsumerConnection(String consumerGroup) {
try {
return mqAdminExt.examineConsumerConnectionInfo(consumerGroup);
}
catch (Exception e) {
throw Throwables.propagate(e);
}
}
@Override
public ConsumerRunningInfo getConsumerRunningInfo(String consumerGroup, String clientId, boolean jstack) {
try {
return mqAdminExt.getConsumerRunningInfo(consumerGroup, clientId, jstack);
}
catch (Exception e) {
throw Throwables.propagate(e);
}
}
}

157
src/main/java/org/apache/rocketmq/dashboard/service/impl/DashboardCollectServiceImpl.java

@ -0,0 +1,157 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
import com.google.common.base.Ticker;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.service.DashboardCollectService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class DashboardCollectServiceImpl implements DashboardCollectService {
@Resource
private RMQConfigure configure;
private final static Logger log = LoggerFactory.getLogger(DashboardCollectServiceImpl.class);
private LoadingCache<String, List<String>> brokerMap = CacheBuilder.newBuilder()
.maximumSize(1000)
.concurrencyLevel(10)
.recordStats()
.ticker(Ticker.systemTicker())
.removalListener(new RemovalListener<Object, Object>() {
@Override
public void onRemoval(RemovalNotification<Object, Object> notification) {
log.debug(notification.getKey() + " was removed, cause is " + notification.getCause());
}
})
.build(
new CacheLoader<String, List<String>>() {
@Override
public List<String> load(String key) {
List<String> list = Lists.newArrayList();
return list;
}
}
);
private LoadingCache<String, List<String>> topicMap = CacheBuilder.newBuilder()
.maximumSize(1000)
.concurrencyLevel(10)
.recordStats()
.ticker(Ticker.systemTicker())
.removalListener(new RemovalListener<Object, Object>() {
@Override
public void onRemoval(RemovalNotification<Object, Object> notification) {
log.debug(notification.getKey() + " was removed, cause is " + notification.getCause());
}
})
.build(
new CacheLoader<String, List<String>>() {
@Override
public List<String> load(String key) {
List<String> list = Lists.newArrayList();
return list;
}
}
);
@Override
public LoadingCache<String, List<String>> getBrokerMap() {
return brokerMap;
}
@Override
public LoadingCache<String, List<String>> getTopicMap() {
return topicMap;
}
@Override
public Map<String, List<String>> jsonDataFile2map(File file) {
List<String> strings;
try {
strings = Files.readLines(file, Charsets.UTF_8);
}
catch (IOException e) {
throw Throwables.propagate(e);
}
StringBuffer sb = new StringBuffer();
for (String string : strings) {
sb.append(string);
}
JSONObject json = (JSONObject) JSONObject.parse(sb.toString());
Set<Map.Entry<String, Object>> entries = json.entrySet();
Map<String, List<String>> map = Maps.newHashMap();
for (Map.Entry<String, Object> entry : entries) {
JSONArray tpsArray = (JSONArray) entry.getValue();
if (tpsArray == null) {
continue;
}
Object[] tpsStrArray = tpsArray.toArray();
List<String> tpsList = Lists.newArrayList();
for (Object tpsObj : tpsStrArray) {
tpsList.add("" + tpsObj);
}
map.put(entry.getKey(), tpsList);
}
return map;
}
@Override
public Map<String, List<String>> getBrokerCache(String date) {
String dataLocationPath = configure.getDashboardCollectData();
File file = new File(dataLocationPath + date + ".json");
if (!file.exists()) {
log.info(String.format("No dashboard data for broker cache data: %s", date));
return Maps.newHashMap();
}
return jsonDataFile2map(file);
}
@Override
public Map<String, List<String>> getTopicCache(String date) {
String dataLocationPath = configure.getDashboardCollectData();
File file = new File(dataLocationPath + date + "_topic" + ".json");
if (!file.exists()) {
log.info(String.format("No dashboard data for data: %s", date));
//throw Throwables.propagate(new ServiceException(1, "This date have't data!"));
return Maps.newHashMap();
}
return jsonDataFile2map(file);
}
}

73
src/main/java/org/apache/rocketmq/dashboard/service/impl/DashboardServiceImpl.java

@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.collect.Lists;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.service.DashboardCollectService;
import org.apache.rocketmq.dashboard.service.DashboardService;
import org.springframework.stereotype.Service;
@Service
public class DashboardServiceImpl implements DashboardService {
@Resource
private DashboardCollectService dashboardCollectService;
/**
* @param date format yyyy-MM-dd
*/
@Override
public Map<String, List<String>> queryBrokerData(String date) {
return dashboardCollectService.getBrokerCache(date);
}
@Override
public Map<String, List<String>> queryTopicData(String date) {
return dashboardCollectService.getTopicCache(date);
}
/**
* @param date format yyyy-MM-dd
* @param topicName
*/
@Override
public List<String> queryTopicData(String date, String topicName) {
if (null != dashboardCollectService.getTopicCache(date)) {
return dashboardCollectService.getTopicCache(date).get(topicName);
}
return null;
}
@Override
public List<String> queryTopicCurrentData() {
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Map<String, List<String>> topicCache = dashboardCollectService.getTopicCache(format.format(date));
List<String> result = Lists.newArrayList();
for (Map.Entry<String, List<String>> entry : topicCache.entrySet()) {
List<String> value = entry.getValue();
result.add(entry.getKey() + "," + value.get(value.size() - 1).split(",")[4]);
}
return result;
}
}

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

Loading…
Cancel
Save