├── .gitignore ├── .travis.yml ├── LICENSE ├── README.adoc ├── pom.xml └── src ├── main ├── assembly │ └── module-assembly.xml ├── java │ └── org │ │ ├── rhq │ │ └── wfly │ │ │ └── monitor │ │ │ ├── extension │ │ │ ├── DiagnosticsAdd.java │ │ │ ├── DiagnosticsDefinition.java │ │ │ ├── DiagnosticsRemove.java │ │ │ ├── DiagnosticsWriteAttributeHandler.java │ │ │ ├── InputAdd.java │ │ │ ├── InputDefinition.java │ │ │ ├── InputRemove.java │ │ │ ├── InputWriteAttributeHandler.java │ │ │ ├── MonitorAdd.java │ │ │ ├── MonitorDefinition.java │ │ │ ├── MonitorLogger.java │ │ │ ├── MonitorRemove.java │ │ │ ├── MonitorWriteAttributeHandler.java │ │ │ ├── RootDefinition.java │ │ │ ├── StorageAdd.java │ │ │ ├── StorageDefinition.java │ │ │ ├── StorageRemove.java │ │ │ ├── StorageWriteAttributeHandler.java │ │ │ ├── SubsystemAdd.java │ │ │ ├── SubsystemDefinition.java │ │ │ ├── SubsystemExtension.java │ │ │ ├── SubsystemParser.java │ │ │ └── SubsystemRemove.java │ │ │ └── service │ │ │ └── RhqMetricsService.java │ │ └── wildfly │ │ └── metrics │ │ └── scheduler │ │ ├── ModelControllerClientFactory.java │ │ ├── SchedulerLogger.java │ │ ├── Service.java │ │ ├── TopologyChangeListener.java │ │ ├── config │ │ ├── Address.java │ │ ├── ConfigLoader.java │ │ ├── Configuration.java │ │ ├── ConfigurationInstance.java │ │ ├── Interval.java │ │ └── ResourceRef.java │ │ ├── diagnose │ │ ├── Diagnostics.java │ │ └── StorageReporter.java │ │ ├── polling │ │ ├── AbstractScheduler.java │ │ ├── ClientFactoryImpl.java │ │ ├── IntervalBasedScheduler.java │ │ ├── IntervalGrouping.java │ │ ├── OperationBuilder.java │ │ ├── ReadAttributeOperationBuilder.java │ │ ├── Scheduler.java │ │ ├── Task.java │ │ ├── TaskGroup.java │ │ └── TaskGrouping.java │ │ └── storage │ │ ├── BufferedStorageDispatcher.java │ │ ├── DataPoint.java │ │ ├── DefaultKeyResolution.java │ │ ├── InfluxStorageAdapter.java │ │ ├── KeyResolution.java │ │ ├── RHQStorageAdapter.java │ │ └── StorageAdapter.java └── resources │ ├── META-INF │ └── services │ │ └── org.jboss.as.controller.Extension │ ├── config │ ├── monitor-domain.xml │ ├── monitor-host.xml │ └── standalone-monitor.xml │ ├── module │ └── main │ │ └── module.xml │ ├── org │ └── rhq │ │ └── wfly │ │ └── monitor │ │ └── extension │ │ └── LocalDescriptions.properties │ ├── schema │ └── wildfly-monitor-subsystem.xsd │ └── subsystem.xml └── test ├── java └── org │ └── rhq │ └── wfly │ └── monitor │ └── extension │ ├── SubsystemBaseParsingTestCase.java │ └── SubsystemParsingTestCase.java └── resources └── org └── rhq └── wfly └── monitor └── extension └── subsystem.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .target 3 | *.jar 4 | *.war 5 | *.ear 6 | wildfly-sender.iml 7 | .idea 8 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 9 | hs_err_pid* 10 | # eclipse files 11 | .classpath 12 | .project 13 | target 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | # ARCHIVED AND NO LONGER MAINTAINED 2 | 3 | = WildFly Monitor 4 | 5 | image:https://travis-ci.org/rhq-project/wildfly-monitor.svg?branch=master["Build Status", link="https://travis-ci.org/rhq-project/wildfly-monitor"] 6 | 7 | This is a module to be deployed into WildFlyAS and which then takes 8 | measurements from the WildFly model and sends them to a https://github.com/rhq-project/wildfly-monitor/wiki/RHQ[RHQ-Metrics server] or https://github.com/rhq-project/wildfly-monitor/wiki/InfluxDB[InfluxDB] 9 | 10 | == Prerequisites 11 | 12 | === Wildfly 8.1.0 13 | 14 | Get and install Wildfly 8.1.0: http://download.jboss.org/wildfly/8.1.0.Final/wildfly-8.1.0.Final.zip 15 | 16 | It's currently been tested against WF 8.1.0 and the default server configuration (standalone-monitor.xml) is configured for WF 8. 17 | But apart from that there should be no reason to not use it on WF 9. 18 | 19 | === RHQ Metrics 20 | 21 | https://github.com/rhq-project/rhq-metrics[RHQ Metrics] is not part of this module. It needs to be installed separately. Please consult the RHQ metrics documentation, 22 | how to install the core metric components and the REST services onto Wildfly 8. 23 | 24 | 25 | == Build & Install 26 | 27 | Build the top level project: 28 | 29 | ---- 30 | $ mvn clean install 31 | ---- 32 | 33 | This will also create a wildfly-monitor-module.zip, that can be installed on Wildfly: 34 | 35 | `unzip target/wildfly-monitor-module.zip -d $WILDFLY_HOME` 36 | 37 | This will add an additional module that contains the monitor extension and subsystem: 38 | 39 | `modules/system/layers/base/org/rhq/metrics/wildfly-monitor/` 40 | 41 | == Package Contents 42 | 43 | The following contents will be installed when you unpack the wildfly-monitor-module.zip: 44 | 45 | .... 46 | modules/system/layers/base/org/rhq/metrics/wildfly-monitor/main/module.xml (1) 47 | modules/system/layers/base/org/rhq/metrics/wildfly-monitor/main/*.jar (2) 48 | standalone/configuration/standalone-monitor.xml (3) 49 | domain/configuration/monitor-domain.xml (4) 50 | domain/configuration/monitor-host.xml (5)` 51 | .... 52 | 53 | . The module descriptor 54 | . Required libraries to run the monitor on Wildfly 55 | . An example configuration for standalone servers 56 | . An example configuration for managed domains 57 | . An example host configuration 58 | 59 | ## Server Configuration Profiles 60 | 61 | The wildfly-monitor-module.zip server profiles for both standalone and domain mode that can be used to start a pre-configured Wildfly instance: 62 | 63 | ### Standalone Mode 64 | 65 | `./bin/standalone.sh -c standalone-monitor.xml -b 127.0.0.1` 66 | 67 | ### Domain Mode 68 | 69 | `./bin/domain.sh --domain-config=monitor-domain.xml --host-config=monitor-host.xml -b 127.0.0.1` 70 | 71 | 72 | ## Get In touch 73 | 74 | The best way to reach out and discuss the monitor subsystem is the RHQ mailing list and/or the Chat Room: 75 | 76 | - Mailing List: https://lists.fedorahosted.org/mailman/listinfo/rhq-devel 77 | - IRC: irc://freenode.org/#rhq 78 | 79 | ## License 80 | 81 | - http://www.apache.org/licenses/LICENSE-2.0.html 82 | 83 | ## Resources 84 | - https://docs.jboss.org/author/display/WFLY8/Documentation 85 | 86 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | 9 | org.rhq.metrics 10 | wildfly-monitor 11 | 0.2.4-SNAPSHOT 12 | 13 | RHQ Metrics WildFly Monitor Subsystem 14 | A WildFly extension that is able to take server metrics and send them to RHQ Metrics. 15 | 16 | jar 17 | 18 | 19 | 0.0.6-SNAPSHOT 20 | 8.1.0.Final 21 | 4.11 22 | 18.0 23 | UTF-8 24 | 8.1.0.Final 25 | 0.2.4 26 | 3.1.0 27 | 3.1.4.GA 28 | 1.2.0.Final 29 | 30 | 31 | 32 | 34 | ${project.artifactId} 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-assembly-plugin 39 | 2.4 40 | 41 | 42 | src/main/assembly/module-assembly.xml 43 | 44 | 45 | 46 | 47 | make-module 48 | package 49 | 50 | single 51 | 52 | 53 | 54 | 55 | 56 | maven-compiler-plugin 57 | 3.1 58 | 59 | 1.7 60 | 1.7 61 | 62 | 63 | 64 | org.apache.maven.plugins 65 | maven-surefire-plugin 66 | 2.16 67 | 68 | true 69 | true 70 | -Xmx512m 71 | 72 | 73 | jboss.home 74 | ${jboss.home} 75 | 76 | 77 | 78 | **/*TestCase.java 79 | 80 | once 81 | 82 | 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-source-plugin 87 | 88 | 89 | attach-sources 90 | 91 | jar 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | org.apache.maven.plugins 102 | maven-compiler-plugin 103 | 3.1 104 | 105 | 106 | org.apache.maven.plugins 107 | maven-source-plugin 108 | 2.4 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | test.debug 120 | 121 | 122 | test.debug 123 | 124 | 125 | 126 | 127 | 128 | -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8797,server=y,suspend=y 129 | 130 | 131 | 132 | 133 | publish 134 | 135 | 136 | 137 | 138 | maven-source-plugin 139 | 140 | 141 | attach-sources 142 | 143 | jar 144 | 145 | 146 | 147 | 148 | 149 | 150 | maven-javadoc-plugin 151 | 152 | 153 | attach-javadocs 154 | 155 | jar 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | install-wf 167 | 168 | 169 | install-wf 170 | 171 | 172 | 173 | 174 | 175 | org.jboss.plugins 176 | wildfly-extension-maven-plugin 177 | 0.1-SNAPSHOT 178 | 179 | ${project.build.directory}/${project.artifactId}-module.zip 180 | ${jboss.home} 181 | 182 | 183 | 184 | build-dist 185 | install 186 | 187 | deploy 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | org.wildfly 202 | wildfly-controller 203 | ${version.wildfly} 204 | 205 | 206 | org.wildfly 207 | wildfly-server 208 | ${version.wildfly} 209 | 210 | 211 | org.wildfly 212 | wildfly-subsystem-test 213 | pom 214 | test 215 | ${version.wildfly} 216 | 217 | 218 | junit 219 | junit 220 | test 221 | ${version.junit} 222 | 223 | 224 | 225 | org.jboss.logging 226 | jboss-logging 227 | ${version.org.jboss.logging.jboss-logging} 228 | 229 | 230 | 231 | org.jboss.logging 232 | jboss-logging-annotations 233 | 235 | provided 236 | true 237 | ${version.org.jboss.logging.jboss-logging-tools} 238 | 239 | 240 | org.jboss.logging 241 | jboss-logging-processor 242 | 244 | provided 245 | true 246 | ${version.org.jboss.logging.jboss-logging-tools} 247 | 248 | 249 | 250 | 251 | 252 | 253 | com.google.guava 254 | guava 255 | ${version.guava} 256 | 257 | 258 | org.rhq.metrics 259 | clients-common 260 | ${rhq-metric.clients-common.version} 261 | 262 | 263 | org.wildfly 264 | wildfly-controller 265 | ${wildfly.version} 266 | 267 | 268 | org.wildfly 269 | wildfly-controller-client 270 | ${wildfly.version} 271 | 272 | 273 | org.wildfly 274 | wildfly-server 275 | 276 | 277 | org.influxdb 278 | influxdb-java 279 | 1.2 280 | 281 | 282 | org.apache.httpcomponents 283 | httpclient 284 | 4.2.1 285 | provided 286 | 287 | 288 | org.wildfly 289 | wildfly-subsystem-test 290 | pom 291 | test 292 | 293 | 294 | io.dropwizard.metrics 295 | metrics-core 296 | ${codehale.version} 297 | 298 | 299 | junit 300 | junit 301 | test 302 | 303 | 304 | org.jboss.logging 305 | jboss-logging-annotations 306 | 308 | provided 309 | true 310 | 311 | 312 | org.jboss.logging 313 | jboss-logging-processor 314 | 316 | provided 317 | true 318 | 319 | 320 | 321 | 322 | 323 | 324 | jboss-public-repository-group 325 | JBoss Public Maven Repository Group 326 | https://repository.jboss.org/nexus/content/groups/public/ 327 | default 328 | 329 | never 330 | 331 | 332 | never 333 | 334 | 335 | 336 | 337 | 338 | 339 | clojars 340 | clojars 341 | https://clojars.org/repo 342 | 343 | 344 | 345 | 346 | 347 | 348 | jboss-snapshots-repository 349 | JBoss Snapshots Repository 350 | https://repository.jboss.org/nexus/content/repositories/snapshots/ 351 | 352 | 353 | 354 | jboss-releases-repository 355 | JBoss Releases Repository 356 | https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/ 357 | 358 | 359 | 360 | local-site-tmp 361 | RHQ-metrics 362 | file:///tmp/rhq-metrics-site 363 | 364 | 365 | 366 | 367 | 368 | 369 | Apache License, Version 2.0 370 | http://www.apache.org/licenses/LICENSE-2.0.txt 371 | repo 372 | 373 | 374 | 375 | 376 | -------------------------------------------------------------------------------- /src/main/assembly/module-assembly.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 21 | module 22 | 23 | zip 24 | 25 | false 26 | 27 | 28 | ${project.basedir}/target/ 29 | modules/system/layers/base/org/rhq/metrics/wildfly-monitor/main 30 | 31 | wildfly-monitor.jar 32 | 33 | 34 | 35 | ${project.basedir}/src/main/resources/module/main 36 | modules/system/layers/base/org/rhq/metrics/wildfly-monitor/main 37 | 38 | module.xml 39 | 40 | 41 | 42 | ${project.basedir}/src/main/resources/config 43 | standalone/configuration/ 44 | 45 | standalone-monitor.xml 46 | 47 | 48 | 49 | ${project.basedir}/src/main/resources/config 50 | domain/configuration/ 51 | 52 | monitor-domain.xml 53 | monitor-host.xml 54 | 55 | 56 | 57 | 58 | 59 | true 60 | true 61 | modules/system/layers/base/org/rhq/metrics/wildfly-monitor/main 62 | 63 | io.dropwizard.metrics:metrics-core 64 | com.google.guava:guava 65 | org.influxdb:influxdb-java 66 | com.squareup.retrofit 67 | com.google.code.gson 68 | com.google.guava:guava 69 | com.squareup.okhttp:okhttp 70 | com.squareup.okio:okio 71 | com.squareup.okhttp:okhttp-urlconnection 72 | org.apache.httpcomponents:httpclient 73 | org.apache.httpcomponents:httpcore 74 | commons-logging:commons-logging 75 | commons-codec:commons-codec 76 | org.rhq.metrics:clients-common 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/DiagnosticsAdd.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AbstractAddStepHandler; 4 | import org.jboss.as.controller.AttributeDefinition; 5 | import org.jboss.as.controller.OperationContext; 6 | import org.jboss.as.controller.OperationFailedException; 7 | import org.jboss.as.controller.PathAddress; 8 | import org.jboss.as.controller.ServiceVerificationHandler; 9 | import org.jboss.as.controller.registry.Resource; 10 | import org.jboss.dmr.ModelNode; 11 | import org.jboss.msc.service.ServiceController; 12 | 13 | import java.util.List; 14 | 15 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; 16 | 17 | /** 18 | * Add a metric to the system 19 | * @author Heiko W. Rupp 20 | */ 21 | public class DiagnosticsAdd extends AbstractAddStepHandler { 22 | 23 | public static final DiagnosticsAdd INSTANCE = new DiagnosticsAdd(); 24 | 25 | private DiagnosticsAdd() { 26 | 27 | } 28 | 29 | @Override 30 | protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException { 31 | for (AttributeDefinition def : DiagnosticsDefinition.ATTRIBUTES) { 32 | def.validateAndSet(operation, model); 33 | } 34 | } 35 | 36 | @Override 37 | protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, 38 | ServiceVerificationHandler verificationHandler, 39 | List> newControllers) throws OperationFailedException { 40 | 41 | final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR)); 42 | ModelNode fullTree = Resource.Tools.readModel(context.readResource(PathAddress.EMPTY_ADDRESS)); 43 | 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/DiagnosticsDefinition.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | 6 | import org.jboss.as.controller.AttributeDefinition; 7 | import org.jboss.as.controller.PathElement; 8 | import org.jboss.as.controller.PersistentResourceDefinition; 9 | import org.jboss.as.controller.SimpleAttributeDefinition; 10 | import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; 11 | import org.jboss.as.controller.registry.ManagementResourceRegistration; 12 | import org.jboss.dmr.ModelType; 13 | 14 | /** 15 | * Definition of a diagnostics handler 16 | * @author Heiko W. Rupp 17 | */ 18 | public class DiagnosticsDefinition extends PersistentResourceDefinition { 19 | 20 | public static final DiagnosticsDefinition INSTANCE = new DiagnosticsDefinition(); 21 | 22 | public static final String DIAGNOSTICS = "diagnostics"; 23 | 24 | static final SimpleAttributeDefinition ENABLED = new SimpleAttributeDefinitionBuilder("enabled", ModelType.BOOLEAN,false) 25 | .build(); 26 | 27 | static final SimpleAttributeDefinition SECONDS = new SimpleAttributeDefinitionBuilder("seconds", ModelType.INT,true) 28 | .build(); 29 | 30 | static final SimpleAttributeDefinition MINUTES = new SimpleAttributeDefinitionBuilder("minutes", ModelType.INT,true) 31 | .build(); 32 | 33 | static AttributeDefinition[] ATTRIBUTES = { 34 | ENABLED, SECONDS, MINUTES 35 | }; 36 | 37 | private DiagnosticsDefinition() { 38 | super(PathElement.pathElement(DIAGNOSTICS), 39 | SubsystemExtension.getResourceDescriptionResolver(DIAGNOSTICS), 40 | DiagnosticsAdd.INSTANCE, 41 | DiagnosticsRemove.INSTANCE 42 | ); 43 | } 44 | 45 | @Override 46 | public void registerAttributes(ManagementResourceRegistration resourceRegistration) { 47 | DiagnosticsWriteAttributeHandler handler = new DiagnosticsWriteAttributeHandler(ATTRIBUTES); 48 | 49 | for (AttributeDefinition attr : ATTRIBUTES) { 50 | resourceRegistration.registerReadWriteAttribute(attr, null, handler); 51 | } 52 | 53 | } 54 | 55 | @Override 56 | public Collection getAttributes() { 57 | return Arrays.asList(ATTRIBUTES); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/DiagnosticsRemove.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AbstractRemoveStepHandler; 4 | import org.jboss.as.controller.OperationContext; 5 | import org.jboss.as.controller.OperationFailedException; 6 | import org.jboss.as.controller.PathAddress; 7 | import org.jboss.dmr.ModelNode; 8 | 9 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; 10 | 11 | /** 12 | * StepHandler for removing a metric 13 | * @author Heiko W. Rupp 14 | */ 15 | public class DiagnosticsRemove extends AbstractRemoveStepHandler { 16 | 17 | public static final DiagnosticsRemove INSTANCE = new DiagnosticsRemove(); 18 | 19 | private DiagnosticsRemove() { 20 | 21 | } 22 | 23 | @Override 24 | protected void performRuntime(OperationContext context, ModelNode operation, 25 | ModelNode model) throws OperationFailedException { 26 | final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR)); 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/DiagnosticsWriteAttributeHandler.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AttributeDefinition; 4 | import org.jboss.as.controller.OperationContext; 5 | import org.jboss.as.controller.OperationFailedException; 6 | import org.jboss.as.controller.PathAddress; 7 | import org.jboss.as.controller.RestartParentWriteAttributeHandler; 8 | import org.jboss.as.controller.ServiceVerificationHandler; 9 | import org.jboss.dmr.ModelNode; 10 | import org.jboss.msc.service.ServiceName; 11 | import org.rhq.wfly.monitor.service.RhqMetricsService; 12 | 13 | /** 14 | * Handler that restarts the service on attribute changes 15 | * @author Heiko W. Rupp 16 | */ 17 | public class DiagnosticsWriteAttributeHandler extends RestartParentWriteAttributeHandler { 18 | 19 | public DiagnosticsWriteAttributeHandler(AttributeDefinition... definitions) { 20 | super(DiagnosticsDefinition.DIAGNOSTICS, definitions); 21 | } 22 | 23 | @Override 24 | protected void recreateParentService(OperationContext context, PathAddress parentAddress, ModelNode parentModel, 25 | ServiceVerificationHandler verificationHandler) throws OperationFailedException { 26 | 27 | } 28 | 29 | @Override 30 | protected ServiceName getParentServiceName(PathAddress parentAddress) { 31 | return RhqMetricsService.SERVICE_NAME.append(parentAddress.getLastElement().getValue()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/InputAdd.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AbstractAddStepHandler; 4 | import org.jboss.as.controller.AttributeDefinition; 5 | import org.jboss.as.controller.OperationContext; 6 | import org.jboss.as.controller.OperationFailedException; 7 | import org.jboss.as.controller.ServiceVerificationHandler; 8 | import org.jboss.dmr.ModelNode; 9 | import org.jboss.msc.service.ServiceController; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * Add a metric to the system 15 | * @author Heiko W. Rupp 16 | */ 17 | public class InputAdd extends AbstractAddStepHandler { 18 | 19 | public static final InputAdd INSTANCE = new InputAdd(); 20 | 21 | private InputAdd() { 22 | 23 | } 24 | 25 | @Override 26 | protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException { 27 | for (AttributeDefinition def : InputDefinition.ATTRIBUTES) { 28 | def.validateAndSet(operation, model); 29 | } 30 | } 31 | 32 | @Override 33 | protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, 34 | ServiceVerificationHandler verificationHandler, 35 | List> newControllers) throws OperationFailedException { 36 | 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/InputDefinition.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | 6 | import org.jboss.as.controller.AttributeDefinition; 7 | import org.jboss.as.controller.PathElement; 8 | import org.jboss.as.controller.PersistentResourceDefinition; 9 | import org.jboss.as.controller.SimpleAttributeDefinition; 10 | import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; 11 | import org.jboss.as.controller.registry.ManagementResourceRegistration; 12 | import org.jboss.dmr.ModelType; 13 | 14 | /** 15 | * Definition of a single metric 16 | * @author Heiko W. Rupp 17 | */ 18 | public class InputDefinition extends PersistentResourceDefinition { 19 | 20 | public static final InputDefinition INSTANCE = new InputDefinition(); 21 | 22 | public static final String DATA_INPUT = "data-input"; 23 | 24 | static final SimpleAttributeDefinition RESOURCE = new SimpleAttributeDefinitionBuilder("resource", ModelType.STRING,false) 25 | .build(); 26 | 27 | static final SimpleAttributeDefinition ATTRIBUTE = new SimpleAttributeDefinitionBuilder("attribute", ModelType.STRING,false) 28 | .build(); 29 | 30 | static final SimpleAttributeDefinition SECONDS = new SimpleAttributeDefinitionBuilder("seconds", ModelType.INT,true) 31 | .build(); 32 | 33 | static final SimpleAttributeDefinition MINUTES = new SimpleAttributeDefinitionBuilder("minutes", ModelType.INT,true) 34 | .build(); 35 | 36 | static final SimpleAttributeDefinition HOURS = new SimpleAttributeDefinitionBuilder("hours", ModelType.INT,true) 37 | .build(); 38 | 39 | static AttributeDefinition[] ATTRIBUTES = { 40 | RESOURCE, 41 | ATTRIBUTE, 42 | SECONDS, 43 | MINUTES, 44 | HOURS 45 | }; 46 | 47 | private InputDefinition() { 48 | super(PathElement.pathElement(DATA_INPUT), 49 | SubsystemExtension.getResourceDescriptionResolver(MonitorDefinition.MONITOR, DATA_INPUT), 50 | InputAdd.INSTANCE, 51 | InputRemove.INSTANCE 52 | ); 53 | } 54 | 55 | @Override 56 | public void registerAttributes(ManagementResourceRegistration resourceRegistration) { 57 | InputWriteAttributeHandler handler = new InputWriteAttributeHandler(ATTRIBUTES); 58 | 59 | for (AttributeDefinition attr : ATTRIBUTES) { 60 | resourceRegistration.registerReadWriteAttribute(attr, null, handler); 61 | } 62 | 63 | } 64 | 65 | @Override 66 | public Collection getAttributes() { 67 | return Arrays.asList(ATTRIBUTES); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/InputRemove.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AbstractRemoveStepHandler; 4 | import org.jboss.as.controller.OperationContext; 5 | import org.jboss.as.controller.OperationFailedException; 6 | import org.jboss.as.controller.PathAddress; 7 | import org.jboss.dmr.ModelNode; 8 | 9 | import org.rhq.wfly.monitor.service.RhqMetricsService; 10 | 11 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; 12 | 13 | /** 14 | * StepHandler for removing a metric 15 | * @author Heiko W. Rupp 16 | */ 17 | public class InputRemove extends AbstractRemoveStepHandler { 18 | 19 | public static final InputRemove INSTANCE = new InputRemove(); 20 | 21 | private InputRemove() { 22 | 23 | } 24 | 25 | @Override 26 | protected void performRuntime(OperationContext context, ModelNode operation, 27 | ModelNode model) throws OperationFailedException { 28 | final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR)); 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/InputWriteAttributeHandler.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AttributeDefinition; 4 | import org.jboss.as.controller.OperationContext; 5 | import org.jboss.as.controller.OperationFailedException; 6 | import org.jboss.as.controller.PathAddress; 7 | import org.jboss.as.controller.RestartParentWriteAttributeHandler; 8 | import org.jboss.as.controller.ServiceVerificationHandler; 9 | import org.jboss.dmr.ModelNode; 10 | import org.jboss.msc.service.ServiceName; 11 | import org.rhq.wfly.monitor.service.RhqMetricsService; 12 | 13 | /** 14 | * Handler that restarts the service on attribute changes 15 | * @author Heiko W. Rupp 16 | */ 17 | public class InputWriteAttributeHandler extends RestartParentWriteAttributeHandler { 18 | 19 | public InputWriteAttributeHandler(AttributeDefinition... definitions) { 20 | super(InputDefinition.DATA_INPUT, definitions); 21 | } 22 | 23 | @Override 24 | protected void recreateParentService( 25 | OperationContext context, PathAddress parentAddress, ModelNode parentModel, 26 | ServiceVerificationHandler verificationHandler) throws OperationFailedException { 27 | 28 | } 29 | 30 | @Override 31 | protected ServiceName getParentServiceName(PathAddress parentAddress) { 32 | return RhqMetricsService.SERVICE_NAME.append(parentAddress.getLastElement().getValue()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/MonitorAdd.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AbstractAddStepHandler; 4 | import org.jboss.as.controller.AttributeDefinition; 5 | import org.jboss.as.controller.OperationContext; 6 | import org.jboss.as.controller.OperationFailedException; 7 | import org.jboss.as.controller.PathAddress; 8 | import org.jboss.as.controller.ServiceVerificationHandler; 9 | import org.jboss.as.controller.registry.Resource; 10 | import org.jboss.dmr.ModelNode; 11 | import org.jboss.msc.service.ServiceController; 12 | 13 | import java.util.List; 14 | 15 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; 16 | 17 | /** 18 | * Adds a monitor to the system 19 | * @author Heiko Braun 20 | */ 21 | public class MonitorAdd extends AbstractAddStepHandler { 22 | 23 | public static final MonitorAdd INSTANCE = new MonitorAdd(); 24 | 25 | private MonitorAdd() { 26 | 27 | } 28 | 29 | @Override 30 | protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException { 31 | for (AttributeDefinition def : MonitorDefinition.ATTRIBUTES) { 32 | def.validateAndSet(operation, model); 33 | } 34 | } 35 | 36 | @Override 37 | protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, 38 | ServiceVerificationHandler verificationHandler, 39 | List> newControllers) throws OperationFailedException { 40 | 41 | final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR)); 42 | ModelNode fullTree = Resource.Tools.readModel(context.readResource(PathAddress.EMPTY_ADDRESS)); 43 | 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/MonitorDefinition.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.List; 6 | 7 | import org.jboss.as.controller.AttributeDefinition; 8 | import org.jboss.as.controller.PathElement; 9 | import org.jboss.as.controller.PersistentResourceDefinition; 10 | import org.jboss.as.controller.SimpleAttributeDefinition; 11 | import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; 12 | import org.jboss.as.controller.registry.ManagementResourceRegistration; 13 | import org.jboss.dmr.ModelType; 14 | 15 | /** 16 | * Definition of a monitor 17 | * @author Heiko Braun 18 | */ 19 | public class MonitorDefinition extends PersistentResourceDefinition { 20 | 21 | public static final MonitorDefinition INSTANCE = new MonitorDefinition(); 22 | 23 | public static final String MONITOR = "server-monitor"; 24 | 25 | static final SimpleAttributeDefinition ENABLED = new SimpleAttributeDefinitionBuilder("enabled", ModelType.BOOLEAN,false) 26 | .build(); 27 | 28 | static final SimpleAttributeDefinition THREADS = new SimpleAttributeDefinitionBuilder("num-threads", ModelType.INT,false) 29 | .build(); 30 | 31 | 32 | static AttributeDefinition[] ATTRIBUTES = { 33 | ENABLED, THREADS 34 | }; 35 | 36 | private MonitorDefinition() { 37 | super(PathElement.pathElement(MONITOR), 38 | SubsystemExtension.getResourceDescriptionResolver(MONITOR), 39 | MonitorAdd.INSTANCE, 40 | MonitorRemove.INSTANCE 41 | ); 42 | } 43 | 44 | @Override 45 | protected List getChildren() { 46 | return Arrays.asList(InputDefinition.INSTANCE); 47 | } 48 | 49 | @Override 50 | public void registerAttributes(ManagementResourceRegistration resourceRegistration) { 51 | MonitorWriteAttributeHandler handler = new MonitorWriteAttributeHandler(ATTRIBUTES); 52 | 53 | for (AttributeDefinition attr : ATTRIBUTES) { 54 | resourceRegistration.registerReadWriteAttribute(attr, null, handler); 55 | } 56 | 57 | } 58 | 59 | @Override 60 | public Collection getAttributes() { 61 | return Arrays.asList(ATTRIBUTES); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/MonitorLogger.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | /** 4 | * @author Heiko Braun 5 | * @since 05/11/14 6 | */ 7 | 8 | import org.jboss.logging.BasicLogger; 9 | import org.jboss.logging.Logger; 10 | import org.jboss.logging.MessageLogger; 11 | 12 | /** 13 | * Log messages for WildFly cassandra module 14 | * @author Heiko Braun 15 | */ 16 | @MessageLogger(projectCode = "<>") 17 | public interface MonitorLogger extends BasicLogger { 18 | /** 19 | * A logger with the category {@code org.rhq.wfly.monitor}. 20 | */ 21 | MonitorLogger LOGGER = Logger.getMessageLogger(MonitorLogger.class, "org.rhq.wfly.monitor"); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/MonitorRemove.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AbstractRemoveStepHandler; 4 | import org.jboss.as.controller.OperationContext; 5 | import org.jboss.as.controller.OperationFailedException; 6 | import org.jboss.as.controller.PathAddress; 7 | import org.jboss.dmr.ModelNode; 8 | 9 | 10 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; 11 | 12 | /** 13 | * Removes a monitor from the system 14 | * @author Heiko Braun 15 | */ 16 | public class MonitorRemove extends AbstractRemoveStepHandler { 17 | 18 | public static final MonitorRemove INSTANCE = new MonitorRemove(); 19 | 20 | private MonitorRemove() { 21 | 22 | } 23 | 24 | @Override 25 | protected void performRuntime(OperationContext context, ModelNode operation, 26 | ModelNode model) throws OperationFailedException { 27 | final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR)); 28 | 29 | /*String metricName = address.getLastElement().getValue(); 30 | RhqMonitorsService service = (RhqMonitorsService) context.getServiceRegistry(true).getService(RhqMonitorsService.SERVICE_NAME).getService(); 31 | service.removeMonitor(metricName);*/ 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/MonitorWriteAttributeHandler.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AttributeDefinition; 4 | import org.jboss.as.controller.OperationContext; 5 | import org.jboss.as.controller.OperationFailedException; 6 | import org.jboss.as.controller.PathAddress; 7 | import org.jboss.as.controller.RestartParentWriteAttributeHandler; 8 | import org.jboss.as.controller.ServiceVerificationHandler; 9 | import org.jboss.dmr.ModelNode; 10 | import org.jboss.msc.service.ServiceName; 11 | import org.rhq.wfly.monitor.service.RhqMetricsService; 12 | 13 | /** 14 | * Handler that restarts the service on attribute changes 15 | * @author Heiko W. Rupp 16 | */ 17 | public class MonitorWriteAttributeHandler extends RestartParentWriteAttributeHandler { 18 | 19 | public MonitorWriteAttributeHandler(AttributeDefinition... definitions) { 20 | super(MonitorDefinition.MONITOR, definitions); 21 | } 22 | 23 | @Override 24 | protected void recreateParentService( 25 | OperationContext context, PathAddress parentAddress, ModelNode parentModel, 26 | ServiceVerificationHandler verificationHandler) throws OperationFailedException { 27 | 28 | } 29 | 30 | @Override 31 | protected ServiceName getParentServiceName(PathAddress parentAddress) { 32 | return RhqMetricsService.SERVICE_NAME.append(parentAddress.getLastElement().getValue()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/RootDefinition.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | import org.jboss.as.controller.AttributeDefinition; 9 | import org.jboss.as.controller.PersistentResourceDefinition; 10 | import org.jboss.as.controller.ReloadRequiredRemoveStepHandler; 11 | 12 | /** 13 | * Definition of the >subsystem element with one attribute 14 | * @author Heiko W. Rupp 15 | */ 16 | public class RootDefinition extends PersistentResourceDefinition { 17 | 18 | public static final RootDefinition INSTANCE = new RootDefinition(); 19 | 20 | 21 | static PersistentResourceDefinition[] CHILDREN = { 22 | StorageDefinition.INSTANCE 23 | }; 24 | 25 | 26 | private RootDefinition() { 27 | super(SubsystemExtension.SUBSYSTEM_PATH, 28 | SubsystemExtension.getResourceDescriptionResolver(), 29 | SubsystemAdd.INSTANCE, 30 | ReloadRequiredRemoveStepHandler.INSTANCE 31 | ); 32 | } 33 | 34 | 35 | 36 | @Override 37 | public Collection getAttributes() { 38 | return Collections.emptySet(); 39 | } 40 | 41 | @Override 42 | protected List getChildren() { 43 | return Arrays.asList(CHILDREN); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/StorageAdd.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import java.util.List; 4 | 5 | import org.jboss.as.controller.AbstractAddStepHandler; 6 | import org.jboss.as.controller.AttributeDefinition; 7 | import org.jboss.as.controller.OperationContext; 8 | import org.jboss.as.controller.OperationFailedException; 9 | import org.jboss.as.controller.PathAddress; 10 | import org.jboss.as.controller.ServiceVerificationHandler; 11 | import org.jboss.as.controller.registry.Resource; 12 | import org.jboss.dmr.ModelNode; 13 | import org.jboss.msc.service.ServiceController; 14 | 15 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; 16 | 17 | /** 18 | * Add a server node 19 | * @author Heiko W. Rupp 20 | */ 21 | class StorageAdd extends AbstractAddStepHandler { 22 | 23 | static final StorageAdd INSTANCE = new StorageAdd(); 24 | 25 | private StorageAdd() { 26 | } 27 | 28 | @Override 29 | protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException { 30 | for (AttributeDefinition def : StorageDefinition.ATTRIBUTES) { 31 | def.validateAndSet(operation, model); 32 | } 33 | 34 | } 35 | 36 | @Override 37 | protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, 38 | ServiceVerificationHandler verificationHandler, 39 | List> newControllers) throws OperationFailedException { 40 | 41 | final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR)); 42 | ModelNode fullTree = Resource.Tools.readModel(context.readResource(PathAddress.EMPTY_ADDRESS)); 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/StorageDefinition.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | 6 | import org.jboss.as.controller.AttributeDefinition; 7 | import org.jboss.as.controller.PathElement; 8 | import org.jboss.as.controller.PersistentResourceDefinition; 9 | import org.jboss.as.controller.SimpleAttributeDefinition; 10 | import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; 11 | import org.jboss.as.controller.registry.AttributeAccess; 12 | import org.jboss.as.controller.registry.ManagementResourceRegistration; 13 | import org.jboss.dmr.ModelType; 14 | 15 | /** 16 | * storage adapter configuration. 17 | * 18 | * @author Heiko W. Rupp 19 | */ 20 | public class StorageDefinition extends PersistentResourceDefinition { 21 | 22 | public static final StorageDefinition INSTANCE = new StorageDefinition(); 23 | 24 | public static final String STORAGE_ADAPTER = "storage-adapter"; 25 | 26 | private StorageDefinition() { 27 | super(PathElement.pathElement(STORAGE_ADAPTER), 28 | SubsystemExtension.getResourceDescriptionResolver(STORAGE_ADAPTER), 29 | StorageAdd.INSTANCE, 30 | StorageRemove.INSTANCE 31 | ); 32 | 33 | } 34 | 35 | static final SimpleAttributeDefinition URL = new SimpleAttributeDefinitionBuilder("url", ModelType.STRING,false) 36 | .addFlag(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) 37 | .setAllowExpression(true) 38 | .build(); 39 | 40 | static final SimpleAttributeDefinition USER = new SimpleAttributeDefinitionBuilder("user", ModelType.STRING,true) 41 | .addFlag(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) 42 | .setAllowExpression(true) 43 | .build(); 44 | 45 | static final SimpleAttributeDefinition PASSWORD = new SimpleAttributeDefinitionBuilder("password", ModelType.STRING,true) 46 | .addFlag(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) 47 | .setAllowExpression(true) 48 | .build(); 49 | 50 | static final SimpleAttributeDefinition TOKEN = new SimpleAttributeDefinitionBuilder("token", ModelType.STRING,true) 51 | .addFlag(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) 52 | .build(); 53 | 54 | static final SimpleAttributeDefinition DB = new SimpleAttributeDefinitionBuilder("db", ModelType.STRING,true) 55 | .addFlag(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) 56 | .build(); 57 | 58 | 59 | static final AttributeDefinition[] ATTRIBUTES = { 60 | URL, 61 | USER, PASSWORD, 62 | TOKEN, DB 63 | }; 64 | 65 | @Override 66 | public void registerAttributes(ManagementResourceRegistration resourceRegistration) { 67 | 68 | StorageWriteAttributeHandler handler = new StorageWriteAttributeHandler(ATTRIBUTES); 69 | 70 | for (AttributeDefinition attr : ATTRIBUTES) { 71 | resourceRegistration.registerReadWriteAttribute(attr, null, handler); 72 | } 73 | } 74 | 75 | @Override 76 | public Collection getAttributes() { 77 | return Arrays.asList(ATTRIBUTES); 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/StorageRemove.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AbstractRemoveStepHandler; 4 | import org.jboss.as.controller.OperationContext; 5 | import org.jboss.as.controller.OperationFailedException; 6 | import org.jboss.dmr.ModelNode; 7 | 8 | import org.rhq.wfly.monitor.service.RhqMetricsService; 9 | 10 | /** 11 | * Handler responsible for removing the subsystem resource from the model 12 | * 13 | * @author Kabir Khan 14 | */ 15 | class StorageRemove extends AbstractRemoveStepHandler { 16 | 17 | static final StorageRemove INSTANCE = new StorageRemove(); 18 | 19 | 20 | private StorageRemove() { 21 | } 22 | 23 | @Override 24 | protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { 25 | //Remove any services installed by the corresponding add handler here 26 | context.removeService(RhqMetricsService.SERVICE_NAME); 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/StorageWriteAttributeHandler.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AttributeDefinition; 4 | import org.jboss.as.controller.OperationContext; 5 | import org.jboss.as.controller.OperationFailedException; 6 | import org.jboss.as.controller.PathAddress; 7 | import org.jboss.as.controller.RestartParentWriteAttributeHandler; 8 | import org.jboss.as.controller.ServiceVerificationHandler; 9 | import org.jboss.dmr.ModelNode; 10 | import org.jboss.msc.service.ServiceName; 11 | import org.rhq.wfly.monitor.service.RhqMetricsService; 12 | 13 | /** 14 | * Handler that restarts the service on attribute changes 15 | * @author Heiko W. Rupp 16 | */ 17 | public class StorageWriteAttributeHandler extends RestartParentWriteAttributeHandler { 18 | 19 | public StorageWriteAttributeHandler(AttributeDefinition... definitions) { 20 | super(StorageDefinition.STORAGE_ADAPTER, definitions); 21 | } 22 | 23 | @Override 24 | protected void recreateParentService(OperationContext context, PathAddress parentAddress, ModelNode parentModel, 25 | ServiceVerificationHandler verificationHandler) throws OperationFailedException { 26 | 27 | } 28 | 29 | @Override 30 | protected ServiceName getParentServiceName(PathAddress parentAddress) { 31 | return RhqMetricsService.SERVICE_NAME.append(parentAddress.getLastElement().getValue()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/SubsystemAdd.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | 4 | import org.jboss.as.controller.AbstractAddStepHandler; 5 | import org.jboss.as.controller.OperationContext; 6 | import org.jboss.as.controller.OperationFailedException; 7 | import org.jboss.as.controller.PathAddress; 8 | import org.jboss.as.controller.ServiceVerificationHandler; 9 | import org.jboss.as.controller.registry.Resource; 10 | import org.jboss.dmr.ModelNode; 11 | import org.jboss.msc.service.ServiceController; 12 | import org.rhq.wfly.monitor.service.RhqMetricsService; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * Handler responsible for adding the subsystem resource to the model. 18 | * In fact there is nothing to do here. 19 | * 20 | * Created by the archetype. 21 | * @author Kabir Khan 22 | */ 23 | class SubsystemAdd extends AbstractAddStepHandler { 24 | 25 | static final SubsystemAdd INSTANCE = new SubsystemAdd(); 26 | 27 | private SubsystemAdd() { 28 | } 29 | 30 | /** 31 | * {@inheritDoc} 32 | */ 33 | @Override 34 | protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException { 35 | model.setEmptyObject(); 36 | } 37 | 38 | 39 | @Override 40 | protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List> newControllers) throws OperationFailedException { 41 | 42 | ModelNode subsystemConfig = Resource.Tools.readModel(context.readResource(PathAddress.EMPTY_ADDRESS)); 43 | 44 | // TODO: the root resource doesn't inlcude the runtime paramters, hence we cannot depict the host/server name & launch-type from it. 45 | //ModelNode systemConfig = Resource.Tools.readModel(context.readResourceFromRoot(PathAddress.EMPTY_ADDRESS, false)); 46 | 47 | // Add the service 48 | newControllers.add( 49 | RhqMetricsService.createService( 50 | context.getServiceTarget(), 51 | verificationHandler, 52 | subsystemConfig 53 | ) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/SubsystemDefinition.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | import org.jboss.as.controller.AttributeDefinition; 9 | import org.jboss.as.controller.PersistentResourceDefinition; 10 | import org.jboss.as.controller.ReloadRequiredRemoveStepHandler; 11 | import org.jboss.as.controller.registry.ManagementResourceRegistration; 12 | 13 | /** 14 | * @author Heiko W. Rupp 15 | */ 16 | public class SubsystemDefinition extends PersistentResourceDefinition { 17 | 18 | public static final SubsystemDefinition INSTANCE = new SubsystemDefinition(); 19 | 20 | private SubsystemDefinition() { 21 | super(SubsystemExtension.SUBSYSTEM_PATH, 22 | SubsystemExtension.getResourceDescriptionResolver(), 23 | //We always need to add an 'add' operation 24 | SubsystemAdd.INSTANCE, 25 | //Every resource that is added, normally needs a remove operation 26 | ReloadRequiredRemoveStepHandler.INSTANCE); 27 | } 28 | 29 | @Override 30 | protected List getChildren() { 31 | return Arrays.asList(StorageDefinition.INSTANCE, MonitorDefinition.INSTANCE, DiagnosticsDefinition.INSTANCE); 32 | } 33 | 34 | @Override 35 | public void registerOperations(ManagementResourceRegistration resourceRegistration) { 36 | super.registerOperations(resourceRegistration); 37 | //you can register additional operations here 38 | } 39 | 40 | @Override 41 | public void registerAttributes(ManagementResourceRegistration resourceRegistration) { 42 | //you can register attributes here 43 | } 44 | 45 | @Override 46 | public Collection getAttributes() { 47 | return Collections.emptyList(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/SubsystemExtension.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.Extension; 4 | import org.jboss.as.controller.ExtensionContext; 5 | import org.jboss.as.controller.PathElement; 6 | import org.jboss.as.controller.SubsystemRegistration; 7 | import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver; 8 | import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler; 9 | import org.jboss.as.controller.parsing.ExtensionParsingContext; 10 | import org.jboss.as.controller.registry.ManagementResourceRegistration; 11 | 12 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM; 13 | 14 | 15 | /** 16 | * @author Kabir Khan 17 | */ 18 | public class SubsystemExtension implements Extension { 19 | 20 | /** 21 | * The name space used for the {@code subsystem} element 22 | */ 23 | public static final String NAMESPACE = "urn:org.rhq.metrics:wildfly-monitor:1.0"; 24 | 25 | /** 26 | * The name of our subsystem within the model. 27 | */ 28 | public static final String SUBSYSTEM_NAME = "wildfly-monitor"; 29 | 30 | /** 31 | * The parser used for parsing our subsystem. 32 | * See below 33 | */ 34 | 35 | protected static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME); 36 | private static final String RESOURCE_NAME = SubsystemExtension.class.getPackage().getName() + ".LocalDescriptions"; 37 | 38 | static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) { 39 | StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME); 40 | if (keyPrefix!=null) { 41 | for (String kp : keyPrefix) { 42 | prefix.append('.').append(kp); 43 | } 44 | } 45 | return new StandardResourceDescriptionResolver(prefix.toString(), RESOURCE_NAME, SubsystemExtension.class.getClassLoader(), true, false); 46 | } 47 | 48 | @Override 49 | public void initializeParsers(ExtensionParsingContext context) { 50 | context.setSubsystemXmlMapping(SUBSYSTEM_NAME, NAMESPACE, SubsystemParser.INSTANCE); 51 | } 52 | 53 | 54 | @Override 55 | public void initialize(ExtensionContext context) { 56 | final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, 1, 0); 57 | final ManagementResourceRegistration registration = subsystem.registerSubsystemModel(SubsystemDefinition.INSTANCE); 58 | registration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, 59 | GenericSubsystemDescribeHandler.INSTANCE); 60 | 61 | subsystem.registerXMLElementWriter(SubsystemParser.INSTANCE); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/SubsystemParser.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import java.util.List; 4 | 5 | import javax.xml.stream.XMLStreamConstants; 6 | import javax.xml.stream.XMLStreamException; 7 | 8 | import org.jboss.as.controller.PathAddress; 9 | import org.jboss.as.controller.PersistentResourceXMLDescription; 10 | import org.jboss.as.controller.persistence.SubsystemMarshallingContext; 11 | import org.jboss.dmr.ModelNode; 12 | import org.jboss.staxmapper.XMLElementReader; 13 | import org.jboss.staxmapper.XMLElementWriter; 14 | import org.jboss.staxmapper.XMLExtendedStreamReader; 15 | import org.jboss.staxmapper.XMLExtendedStreamWriter; 16 | 17 | import static org.jboss.as.controller.PersistentResourceXMLDescription.builder; 18 | 19 | /** 20 | * The subsystem parser, which uses stax to read and write to and from xml 21 | * 22 | * @author Heiko W. Rupp 23 | */ 24 | class SubsystemParser 25 | implements XMLStreamConstants, XMLElementReader>, XMLElementWriter { 26 | 27 | public static final SubsystemParser INSTANCE = new SubsystemParser(); 28 | 29 | private final static PersistentResourceXMLDescription xmlDescription; 30 | 31 | static { 32 | xmlDescription = builder(RootDefinition.INSTANCE) 33 | .addChild( 34 | builder(StorageDefinition.INSTANCE) 35 | .addAttributes(StorageDefinition.ATTRIBUTES) 36 | ) 37 | .addChild( 38 | 39 | builder(MonitorDefinition.INSTANCE) 40 | .setXmlElementName(MonitorDefinition.MONITOR) 41 | .addAttributes(MonitorDefinition.ATTRIBUTES) 42 | .addChild( 43 | builder(InputDefinition.INSTANCE) 44 | .setXmlElementName(InputDefinition.DATA_INPUT) 45 | .addAttributes(InputDefinition.ATTRIBUTES) 46 | ) 47 | ) 48 | .addChild( 49 | builder(DiagnosticsDefinition.INSTANCE) 50 | .addAttributes(DiagnosticsDefinition.ATTRIBUTES) 51 | ) 52 | .build(); 53 | 54 | } 55 | 56 | 57 | private SubsystemParser() { 58 | 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | */ 64 | @Override 65 | public void writeContent(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException { 66 | 67 | ModelNode model = new ModelNode(); 68 | model.get(RootDefinition.INSTANCE.getPathElement().getKeyValuePair()).set(context.getModelNode());//this is bit of workaround for SPRD to work properly 69 | xmlDescription.persist(writer, model, SubsystemExtension.NAMESPACE); 70 | } 71 | 72 | /** 73 | * {@inheritDoc} 74 | */ 75 | @Override 76 | public void readElement(XMLExtendedStreamReader reader, List list) throws XMLStreamException { 77 | xmlDescription.parse(reader, PathAddress.EMPTY_ADDRESS, list); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/extension/SubsystemRemove.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.controller.AbstractRemoveStepHandler; 4 | import org.jboss.as.controller.OperationContext; 5 | import org.jboss.as.controller.OperationFailedException; 6 | import org.jboss.dmr.ModelNode; 7 | 8 | /** 9 | * Handler responsible for removing the subsystem resource from the model 10 | * 11 | * @author Kabir Khan 12 | */ 13 | class SubsystemRemove extends AbstractRemoveStepHandler { 14 | 15 | static final SubsystemRemove INSTANCE = new SubsystemRemove(); 16 | 17 | 18 | private SubsystemRemove() { 19 | } 20 | 21 | @Override 22 | protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { 23 | //Remove any services installed by the corresponding add handler here 24 | //context.removeService(ServiceName.of("some", "name")); 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/rhq/wfly/monitor/service/RhqMetricsService.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.service; 2 | 3 | import org.jboss.as.controller.ControlledProcessState; 4 | import org.jboss.as.controller.ControlledProcessStateService; 5 | import org.jboss.as.controller.ModelController; 6 | import org.jboss.as.controller.PathAddress; 7 | import org.jboss.as.controller.ServiceVerificationHandler; 8 | import org.jboss.as.controller.client.ModelControllerClient; 9 | import org.jboss.as.server.ServerEnvironment; 10 | import org.jboss.as.server.ServerEnvironmentService; 11 | import org.jboss.as.server.Services; 12 | import org.jboss.dmr.ModelNode; 13 | import org.jboss.dmr.Property; 14 | import org.jboss.msc.service.Service; 15 | import org.jboss.msc.service.ServiceController; 16 | import org.jboss.msc.service.ServiceName; 17 | import org.jboss.msc.service.ServiceTarget; 18 | import org.jboss.msc.service.StartContext; 19 | import org.jboss.msc.service.StartException; 20 | import org.jboss.msc.service.StopContext; 21 | import org.jboss.msc.value.InjectedValue; 22 | import org.jboss.threads.JBossThreadFactory; 23 | import org.rhq.wfly.monitor.extension.MonitorLogger; 24 | import org.wildfly.metrics.scheduler.ModelControllerClientFactory; 25 | import org.wildfly.metrics.scheduler.config.Configuration; 26 | import org.wildfly.metrics.scheduler.config.ConfigurationInstance; 27 | import org.wildfly.metrics.scheduler.config.Interval; 28 | import org.wildfly.metrics.scheduler.config.ResourceRef; 29 | import org.wildfly.security.manager.action.GetAccessControlContextAction; 30 | 31 | import java.beans.PropertyChangeEvent; 32 | import java.beans.PropertyChangeListener; 33 | import java.io.IOException; 34 | import java.util.List; 35 | import java.util.concurrent.ExecutorService; 36 | import java.util.concurrent.Executors; 37 | import java.util.concurrent.ThreadFactory; 38 | import java.util.concurrent.TimeUnit; 39 | 40 | import static java.security.AccessController.doPrivileged; 41 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.*; 42 | 43 | /** 44 | * A service that gathers values from the system and sends them to a RHQ Metrics Server 45 | * @author Heiko W. Rupp 46 | */ 47 | public class RhqMetricsService implements Service { 48 | 49 | private static final String LAUNCH_TYPE = "launch-type"; 50 | private static final String DOMAIN = "domain"; 51 | private static final String HOST = "host"; 52 | private static final String NAME = "name"; 53 | private static final String RESULT = "result"; 54 | 55 | private Interval diagnosticsInterval; 56 | private boolean diagnosticsEnabled = false; 57 | private boolean enabled = false; 58 | 59 | private ConfigurationInstance schedulerConfig; 60 | private org.wildfly.metrics.scheduler.Service schedulerService; 61 | 62 | private final InjectedValue modelControllerValue = new InjectedValue<>(); 63 | private final InjectedValue serverEnvironmentValue = new InjectedValue<>(); 64 | private final InjectedValue processStateValue = new InjectedValue<>(); 65 | 66 | public static final ServiceName SERVICE_NAME = ServiceName.JBOSS.append("rhq", "wildfly-monitor"); 67 | private PropertyChangeListener serverStateListener; 68 | 69 | 70 | public RhqMetricsService(ModelNode config) { 71 | 72 | // the actual scheduler config 73 | this.schedulerConfig = new ConfigurationInstance(); 74 | 75 | Property storageAdapter = config.get("storage-adapter").asPropertyList().get(0); 76 | List monitors = config.get("server-monitor").asPropertyList(); 77 | Property diagnostics = config.get("diagnostics").asPropertyList().get(0); 78 | 79 | if(monitors.size()==1) 80 | { 81 | Property monitor = monitors.get(0); 82 | ModelNode monitorCfg = monitor.getValue(); 83 | if(monitorCfg.get("enabled").asBoolean()) 84 | { 85 | this.enabled = true; 86 | 87 | // parse storage adapter 88 | ModelNode storageAdapterCfg = storageAdapter.getValue(); 89 | schedulerConfig.setStorageAdapter(Configuration.Storage.valueOf(storageAdapter.getName().toUpperCase())); 90 | schedulerConfig.setStorageUrl(storageAdapterCfg.get("url").asString()); 91 | schedulerConfig.setStorageDb(storageAdapterCfg.get("db").asString()); 92 | 93 | if(storageAdapterCfg.hasDefined("user")) 94 | schedulerConfig.setStorageUser(storageAdapterCfg.get("user").asString()); 95 | 96 | if(storageAdapterCfg.hasDefined("password")) 97 | schedulerConfig.setStoragePassword(storageAdapterCfg.get("password").asString()); 98 | 99 | if(storageAdapterCfg.hasDefined("token")) 100 | schedulerConfig.setStorageToken(storageAdapterCfg.get("token").asString()); 101 | 102 | // monitoring setup 103 | schedulerConfig.setSchedulerThreads(monitorCfg.get("num-threads").asInt()); 104 | 105 | List metrics = monitorCfg.get("data-input").asPropertyList(); 106 | for (Property metric : metrics) { 107 | ModelNode metricCfg = metric.getValue(); 108 | 109 | Interval interval = null; 110 | if (metricCfg.hasDefined("seconds")) { 111 | interval = new Interval(metricCfg.get("seconds").asInt(), TimeUnit.SECONDS); 112 | } 113 | else if (metricCfg.hasDefined("minutes")) 114 | { 115 | interval = new Interval(metricCfg.get("minutes").asInt(), TimeUnit.MINUTES); 116 | } 117 | else if(metricCfg.hasDefined("hours")) 118 | { 119 | interval = new Interval(metricCfg.get("hours").asInt(), TimeUnit.HOURS); 120 | } 121 | 122 | 123 | ResourceRef ref = new ResourceRef( 124 | metricCfg.get("resource").asString(), 125 | metricCfg.get("attribute").asString(), 126 | interval 127 | ); 128 | 129 | schedulerConfig.addResourceRef(ref); 130 | 131 | } 132 | 133 | // diagnostics 134 | ModelNode diagnosticsCfg = diagnostics.getValue(); 135 | schedulerConfig.setDiagnostics(Configuration.Diagnostics.valueOf(diagnostics.getName().toUpperCase())); 136 | 137 | if(diagnosticsCfg.hasDefined("seconds")) 138 | { 139 | this.diagnosticsEnabled = diagnosticsCfg.get("enabled").asBoolean(); 140 | this.diagnosticsInterval = new Interval(diagnosticsCfg.get("seconds").asInt(), TimeUnit.SECONDS); 141 | } 142 | else if(diagnosticsCfg.hasDefined("minutes")) 143 | { 144 | this.diagnosticsEnabled = diagnosticsCfg.get("enabled").asBoolean(); 145 | this.diagnosticsInterval = new Interval(diagnosticsCfg.get("minutes").asInt(), TimeUnit.MINUTES); 146 | } 147 | 148 | } 149 | } 150 | 151 | } 152 | 153 | public static ServiceController createService(final ServiceTarget target, 154 | final ServiceVerificationHandler verificationHandler, 155 | ModelNode config) { 156 | 157 | RhqMetricsService service = new RhqMetricsService(config); 158 | 159 | return target.addService(SERVICE_NAME, service) 160 | .addDependency(ServerEnvironmentService.SERVICE_NAME, ServerEnvironment.class, 161 | service.serverEnvironmentValue) 162 | .addDependency(Services.JBOSS_SERVER_CONTROLLER, ModelController.class, 163 | service.modelControllerValue) 164 | .addDependency(ControlledProcessStateService.SERVICE_NAME, ControlledProcessStateService.class, 165 | service.processStateValue) 166 | .addListener(verificationHandler) 167 | .setInitialMode(ServiceController.Mode.ACTIVE) 168 | .install(); 169 | } 170 | 171 | 172 | @Override 173 | public void start(final StartContext startContext) throws StartException { 174 | 175 | 176 | if (this.enabled) { 177 | 178 | 179 | // deferred startup: we have to wait until the server is running before we can monitor the subsystems (parallel service startup) 180 | ControlledProcessStateService stateService = processStateValue.getValue(); 181 | serverStateListener = new PropertyChangeListener() { 182 | @Override 183 | public void propertyChange(PropertyChangeEvent evt) { 184 | if (ControlledProcessState.State.RUNNING.equals(evt.getNewValue())) { 185 | 186 | MonitorLogger.LOGGER.infof("Starting monitoring subsystem"); 187 | startScheduler(startContext); 188 | } 189 | } 190 | }; 191 | stateService.addPropertyChangeListener(serverStateListener); 192 | 193 | } 194 | 195 | } 196 | 197 | private void startScheduler(StartContext startContext) { 198 | 199 | final ThreadFactory threadFactory = new JBossThreadFactory( 200 | new ThreadGroup("RHQ-Metrics-threads"), 201 | Boolean.FALSE, null, "%G - %t", null, null, 202 | doPrivileged(GetAccessControlContextAction.getInstance())); 203 | 204 | final ExecutorService executorService = Executors.newCachedThreadPool(threadFactory); 205 | final ModelControllerClient client = modelControllerValue.getValue().createClient(executorService); 206 | 207 | 208 | // create scheduler service 209 | schedulerService = new org.wildfly.metrics.scheduler.Service(schedulerConfig, new ModelControllerClientFactory() { 210 | @Override 211 | public ModelControllerClient createClient() { 212 | return modelControllerValue.getValue().createClient(executorService); 213 | } 214 | }); 215 | 216 | // Get the server name from the runtime model 217 | // TODO: this should be changed to OperationContext.readResourceFromRoot(...) 218 | boolean isDomainMode = getAttribute(client, LAUNCH_TYPE).equalsIgnoreCase(DOMAIN); 219 | 220 | String hostName = null; 221 | String serverName = null; 222 | 223 | if(isDomainMode) 224 | { 225 | hostName = getAttribute(client, HOST); 226 | serverName = getAttribute(client, NAME); 227 | } 228 | else 229 | { 230 | hostName = ""; 231 | serverName = getAttribute(client, NAME); 232 | } 233 | 234 | // Create a http client 235 | schedulerService.start(hostName, serverName); 236 | 237 | // enabled diagnostics if needed 238 | if(diagnosticsEnabled) { 239 | schedulerService.reportEvery(diagnosticsInterval.getVal(), diagnosticsInterval.getUnit()); 240 | } 241 | 242 | } 243 | 244 | @Override 245 | public void stop(StopContext stopContext) { 246 | 247 | MonitorLogger.LOGGER.infof("Stopping monitoring subsystem"); 248 | 249 | // shutdown scheduler 250 | if(schedulerService!=null) 251 | schedulerService.stop(); 252 | 253 | // cleanup the state listener 254 | if(serverStateListener!=null) 255 | processStateValue.getValue().removePropertyChangeListener(serverStateListener); 256 | 257 | } 258 | 259 | @Override 260 | public RhqMetricsService getValue() throws IllegalStateException, IllegalArgumentException { 261 | return this; 262 | } 263 | 264 | private String getStringAttribute(ModelControllerClient client, String attributeName, PathAddress path) { 265 | ModelNode result = getModelNode(client, attributeName, path); 266 | return result.asString(); 267 | } 268 | 269 | private ModelNode getModelNode(ModelControllerClient client, String attributeName, PathAddress address){ 270 | try { 271 | ModelNode request = new ModelNode(); 272 | 273 | if (address !=null) { 274 | 275 | request.get(ADDRESS).set(address.toModelNode()); 276 | } 277 | 278 | request.get(OP).set(READ_ATTRIBUTE_OPERATION); 279 | request.get(NAME).set(attributeName); 280 | ModelNode resultNode = client.execute(request); 281 | // get the inner "result" -- should check for failure and so on... 282 | resultNode = resultNode.get(RESULT); 283 | return resultNode; 284 | } catch (IOException e) { 285 | throw new RuntimeException(e); 286 | } 287 | } 288 | 289 | private String getAttribute(ModelControllerClient client, String attributeName) { 290 | try { 291 | ModelNode request = new ModelNode(); 292 | request.get(ADDRESS).setEmptyList(); 293 | request.get(OP).set(READ_ATTRIBUTE_OPERATION); 294 | request.get(NAME).set(attributeName); 295 | ModelNode resultNode = client.execute(request); 296 | // get the inner "result" -- should check for failure and so on... 297 | resultNode = resultNode.get(RESULT); 298 | return resultNode.asString(); 299 | } catch (IOException e) { 300 | throw new RuntimeException(e); 301 | } 302 | } 303 | 304 | } 305 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/ModelControllerClientFactory.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler; 2 | 3 | import org.jboss.as.controller.client.ModelControllerClient; 4 | 5 | /** 6 | * @author Heiko Braun 7 | * @since 17/10/14 8 | */ 9 | public interface ModelControllerClientFactory { 10 | ModelControllerClient createClient(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/SchedulerLogger.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler; 2 | 3 | /** 4 | * @author Heiko Braun 5 | * @since 05/11/14 6 | */ 7 | 8 | import org.jboss.logging.BasicLogger; 9 | import org.jboss.logging.Logger; 10 | import org.jboss.logging.MessageLogger; 11 | 12 | /** 13 | * Log messages for WildFly cassandra module 14 | * @author Heiko Braun 15 | */ 16 | @MessageLogger(projectCode = "<>") 17 | public interface SchedulerLogger extends BasicLogger { 18 | /** 19 | * A logger with the category {@code org.wildfly.metrics.scheduler}. 20 | */ 21 | SchedulerLogger LOGGER = Logger.getMessageLogger(SchedulerLogger.class, "org.wildfly.metrics.scheduler"); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/Service.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler; 2 | 3 | import com.codahale.metrics.ConsoleReporter; 4 | import com.codahale.metrics.Counter; 5 | import com.codahale.metrics.Meter; 6 | import com.codahale.metrics.MetricRegistry; 7 | import com.codahale.metrics.ScheduledReporter; 8 | import com.codahale.metrics.Timer; 9 | import org.wildfly.metrics.scheduler.config.Address; 10 | import org.wildfly.metrics.scheduler.config.Configuration; 11 | import org.wildfly.metrics.scheduler.config.ResourceRef; 12 | import org.wildfly.metrics.scheduler.diagnose.Diagnostics; 13 | import org.wildfly.metrics.scheduler.diagnose.StorageReporter; 14 | import org.wildfly.metrics.scheduler.polling.ClientFactoryImpl; 15 | import org.wildfly.metrics.scheduler.polling.IntervalBasedScheduler; 16 | import org.wildfly.metrics.scheduler.polling.Scheduler; 17 | import org.wildfly.metrics.scheduler.polling.Task; 18 | import org.wildfly.metrics.scheduler.storage.BufferedStorageDispatcher; 19 | import org.wildfly.metrics.scheduler.storage.InfluxStorageAdapter; 20 | import org.wildfly.metrics.scheduler.storage.RHQStorageAdapter; 21 | import org.wildfly.metrics.scheduler.storage.StorageAdapter; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | import java.util.concurrent.TimeUnit; 26 | 27 | import static com.codahale.metrics.MetricRegistry.name; 28 | import static java.util.concurrent.TimeUnit.MILLISECONDS; 29 | 30 | /** 31 | * The core service that creates task lists from a {@link org.wildfly.metrics.scheduler.config.Configuration} 32 | * and schedules work through a {@link org.wildfly.metrics.scheduler.polling.Scheduler}. 33 | * The resulting data will be pushed to a {@link org.wildfly.metrics.scheduler.storage.StorageAdapter} 34 | * 35 | * @author Heiko Braun 36 | * @since 10/10/14 37 | */ 38 | public class Service implements TopologyChangeListener { 39 | 40 | private final StorageAdapter storageAdapter; 41 | private Configuration configuration; 42 | private Scheduler scheduler; 43 | private Diagnostics diagnostics; 44 | private ScheduledReporter reporter; 45 | private boolean started = false; 46 | private BufferedStorageDispatcher completionHandler; 47 | 48 | /** 49 | * 50 | * @param configuration 51 | */ 52 | public Service(Configuration configuration) { 53 | this(configuration, new ClientFactoryImpl( 54 | configuration.getHost(), 55 | configuration.getPort(), 56 | configuration.getUsername(), 57 | configuration.getPassword()) 58 | ); 59 | } 60 | 61 | /** 62 | * 63 | * @param configuration 64 | * @param clientFactory 65 | */ 66 | public Service(Configuration configuration, ModelControllerClientFactory clientFactory) { 67 | 68 | this.configuration = configuration; 69 | 70 | final MetricRegistry metrics = new MetricRegistry(); 71 | 72 | this.diagnostics = createDiagnostics(metrics); 73 | 74 | if(Configuration.Storage.RHQ == configuration.getStorageAdapter()) 75 | { 76 | this.storageAdapter = new RHQStorageAdapter(); 77 | } 78 | else 79 | { 80 | this.storageAdapter = new InfluxStorageAdapter(); 81 | } 82 | 83 | this.storageAdapter.setConfiguration(configuration); 84 | this.storageAdapter.setDiagnostics(diagnostics); 85 | 86 | if(Configuration.Diagnostics.CONSOLE == configuration.getDiagnostics()) { 87 | 88 | this.reporter = ConsoleReporter.forRegistry(metrics) 89 | .convertRatesTo(TimeUnit.SECONDS) 90 | .convertDurationsTo(MILLISECONDS) 91 | .build(); 92 | } 93 | else 94 | { 95 | this.reporter = StorageReporter.forRegistry(metrics, storageAdapter) 96 | .convertRatesTo(TimeUnit.SECONDS) 97 | .convertDurationsTo(MILLISECONDS) 98 | .build(); 99 | } 100 | 101 | this.completionHandler = new BufferedStorageDispatcher(storageAdapter, diagnostics); 102 | 103 | this.scheduler = new IntervalBasedScheduler( 104 | clientFactory, 105 | diagnostics, 106 | configuration.getSchedulerThreads() 107 | ); 108 | } 109 | 110 | private Diagnostics createDiagnostics(final MetricRegistry metrics) { 111 | return new Diagnostics() { 112 | 113 | private final Timer requestTimer = metrics.timer(name("dmr-request-timer")); 114 | private final Meter delayCounter = metrics.meter(name("task-delay-rate")); 115 | private final Meter taskErrorCounter = metrics.meter(name("task-error-rate")); 116 | private final Meter storageError = metrics.meter(name("storage-error-rate")); 117 | private final Counter storageBuffer = metrics.counter(name("storage-buffer-size")); 118 | 119 | @Override 120 | public Timer getRequestTimer() { 121 | return requestTimer; 122 | } 123 | 124 | @Override 125 | public Meter getDelayedRate() { 126 | return delayCounter; 127 | } 128 | 129 | @Override 130 | public Meter getErrorRate() { 131 | return taskErrorCounter; 132 | } 133 | 134 | @Override 135 | public Meter getStorageErrorRate() { 136 | return storageError; 137 | } 138 | 139 | @Override 140 | public Counter getStorageBufferSize() { 141 | return storageBuffer; 142 | } 143 | }; 144 | } 145 | 146 | public void start(String host, String server) { 147 | 148 | // turn ResourceRef into Tasks (relative to absolute addresses ...) 149 | List tasks = createTasks(host, server, configuration.getResourceRefs()); 150 | this.completionHandler.start(); 151 | this.scheduler.schedule(tasks, completionHandler); 152 | } 153 | 154 | private List createTasks(String host, String server, List resourceRefs) { 155 | List tasks = new ArrayList<>(); 156 | for (ResourceRef ref : resourceRefs) { 157 | 158 | // parse sub references (complex attribute support) 159 | String attribute = ref.getAttribute(); 160 | String subref = null; 161 | int i = attribute.indexOf("#"); 162 | if(i>0) { 163 | subref = attribute.substring(i+1, attribute.length()); 164 | attribute = attribute.substring(0, i); 165 | } 166 | 167 | tasks.add(new Task(host, server, Address.apply(ref.getAddress()), attribute, subref, ref.getInterval())); 168 | } 169 | return tasks; 170 | } 171 | 172 | public void stop() { 173 | this.completionHandler.shutdown(); 174 | this.scheduler.shutdown(); 175 | this.reporter.stop(); 176 | this.reporter.report(); 177 | } 178 | 179 | @Override 180 | public void onChange() { 181 | // shutdown scheduler 182 | // recalculate tasks 183 | // restart scheduler 184 | } 185 | 186 | public void reportEvery(int period, TimeUnit unit) { 187 | if(!started) 188 | reporter.start(period, unit); 189 | } 190 | 191 | 192 | 193 | 194 | 195 | } 196 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/TopologyChangeListener.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler; 2 | 3 | /** 4 | * The service rebuilds the task list when the topology of a domain changes. 5 | * 6 | * @author Heiko Braun 7 | * @since 10/10/14 8 | */ 9 | public interface TopologyChangeListener { 10 | void onChange(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/config/Address.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.config; 23 | 24 | import com.google.common.base.CharMatcher; 25 | import com.google.common.base.Joiner; 26 | import com.google.common.base.Splitter; 27 | import com.google.common.collect.Iterators; 28 | 29 | import java.util.ArrayList; 30 | import java.util.Collections; 31 | import java.util.Iterator; 32 | import java.util.List; 33 | 34 | /** 35 | * @author Harald Pehl 36 | */ 37 | public class Address implements Iterable { 38 | 39 | public static Address apply(String address) { 40 | List tokens = address == null ? Collections.emptyList() : 41 | Splitter.on(CharMatcher.anyOf("/=")) 42 | .trimResults() 43 | .omitEmptyStrings() 44 | .splitToList(address); 45 | 46 | List tuples = new ArrayList<>(tokens.size() / 2 + 1); 47 | for (Iterator iterator = tokens.iterator(); iterator.hasNext(); ) { 48 | String type = iterator.next(); 49 | String name = iterator.hasNext() ? iterator.next() : ""; 50 | tuples.add(new Tuple(type, name)); 51 | } 52 | 53 | return new Address(tuples); 54 | } 55 | 56 | 57 | private final List tuples; 58 | 59 | private Address(final List tuples) { 60 | this.tuples = new ArrayList<>(); 61 | if (tuples != null) { 62 | this.tuples.addAll(tuples); 63 | } 64 | } 65 | 66 | @Override 67 | public boolean equals(final Object o) { 68 | if (this == o) { return true; } 69 | if (!(o instanceof Address)) { return false; } 70 | 71 | Address address = (Address) o; 72 | 73 | if (!tuples.equals(address.tuples)) { return false; } 74 | 75 | return true; 76 | } 77 | 78 | @Override 79 | public int hashCode() { 80 | return tuples.hashCode(); 81 | } 82 | 83 | @Override 84 | public String toString() { 85 | return Joiner.on('/').join(tuples); 86 | } 87 | 88 | @Override 89 | public Iterator iterator() { 90 | return Iterators.unmodifiableIterator(tuples.iterator()); 91 | } 92 | 93 | public boolean isEmpty() {return tuples.isEmpty();} 94 | 95 | public boolean isBalanced() { 96 | for (Tuple tuple : this) { 97 | if (tuple.getValue() == null || tuple.getValue().length() == 0) { 98 | return false; 99 | } 100 | } 101 | return true; 102 | } 103 | 104 | public boolean startsWith(Tuple tuple) { 105 | return !tuples.isEmpty() && tuples.get(0).equals(tuple); 106 | } 107 | 108 | 109 | /** 110 | * @author Harald Pehl 111 | */ 112 | public static class Tuple { 113 | 114 | public static Tuple apply(String tuple) { 115 | if (tuple == null) { 116 | throw new IllegalArgumentException("Tuple must not be null"); 117 | } 118 | List tuples = Splitter.on('=') 119 | .omitEmptyStrings() 120 | .trimResults() 121 | .splitToList(tuple); 122 | if (tuples.isEmpty() || tuples.size() != 2) { 123 | throw new IllegalArgumentException("Malformed tuple: " + tuple); 124 | } 125 | return new Tuple(tuples.get(0), tuples.get(1)); 126 | } 127 | 128 | private final String key; 129 | private final String value; 130 | 131 | private Tuple(final String key, final String value) { 132 | this.key = key; 133 | this.value = value; 134 | } 135 | 136 | @Override 137 | public boolean equals(final Object o) { 138 | if (this == o) { return true; } 139 | if (!(o instanceof Tuple)) { return false; } 140 | 141 | Tuple that = (Tuple) o; 142 | 143 | if (!value.equals(that.value)) { return false; } 144 | if (!key.equals(that.key)) { return false; } 145 | 146 | return true; 147 | } 148 | 149 | @Override 150 | public int hashCode() { 151 | int result = key.hashCode(); 152 | result = 31 * result + value.hashCode(); 153 | return result; 154 | } 155 | 156 | @Override 157 | public String toString() { 158 | return key + "=" + value; 159 | } 160 | 161 | public String getKey() { 162 | return key; 163 | } 164 | 165 | public String getValue() { 166 | return value; 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/config/ConfigLoader.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.config; 2 | 3 | /** 4 | * @author Heiko Braun 5 | * @since 10/10/14 6 | */ 7 | public interface ConfigLoader { 8 | Configuration load(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/config/Configuration.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.config; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author Heiko Braun 7 | * @since 13/10/14 8 | */ 9 | public interface Configuration { 10 | 11 | public enum Diagnostics {STORAGE, CONSOLE}; 12 | public enum Storage {RHQ, INFLUX} 13 | 14 | /** 15 | * The host controller host. 16 | * @return 17 | */ 18 | String getHost(); 19 | 20 | /** 21 | * The host controller port. 22 | * 23 | * @return 24 | */ 25 | int getPort(); 26 | 27 | /** 28 | * Host controller user 29 | * @return 30 | */ 31 | String getUsername(); 32 | 33 | /** 34 | * Host controller password 35 | * @return 36 | */ 37 | String getPassword(); 38 | 39 | /** 40 | * Number of threads the scheduler uses to poll for new data. 41 | * 42 | * @return 43 | */ 44 | int getSchedulerThreads(); 45 | 46 | /** 47 | * The resources that are to be monitored. 48 | * {@link org.wildfly.metrics.scheduler.config.ResourceRef}'s use relative addresses. 49 | * The core {@link org.wildfly.metrics.scheduler.Service} will resolve it against absolute address within a Wildfly domain. 50 | * 51 | * @return 52 | */ 53 | List getResourceRefs(); 54 | 55 | Storage getStorageAdapter(); 56 | 57 | String getStorageUrl(); 58 | 59 | String getStorageUser(); 60 | 61 | String getStoragePassword(); 62 | 63 | String getStorageDBName(); 64 | 65 | String getStorageToken(); 66 | 67 | Diagnostics getDiagnostics(); 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/config/ConfigurationInstance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.config; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Collections; 26 | import java.util.List; 27 | 28 | /** 29 | * A collection of {@link ResourceRef}s with a unique id. 30 | * 31 | * @author Harald Pehl 32 | */ 33 | public class ConfigurationInstance implements Configuration { 34 | 35 | private final List resourceRefs; 36 | private int schedulerThreads = 2; 37 | 38 | private String host; 39 | private int port; 40 | private String user; 41 | private String password; 42 | 43 | private String storageUrl = null; 44 | private String storageUser = null; 45 | private String storagePassword = null; 46 | private String storageDb = null; 47 | private String storageToken = null; 48 | private Storage storageAdapter = Storage.INFLUX; 49 | 50 | private Diagnostics diagnostics = Diagnostics.CONSOLE; 51 | 52 | public ConfigurationInstance() { 53 | this("localhost", 9990, new ArrayList()); 54 | } 55 | 56 | public ConfigurationInstance(String host, int port) { 57 | this(host, port, new ArrayList()); 58 | } 59 | 60 | public ConfigurationInstance(String host, int port, final List resourceRefs) { 61 | this.host = host; 62 | this.port = port; 63 | this.resourceRefs = resourceRefs; 64 | } 65 | 66 | public List getResourceRefs() { 67 | return Collections.unmodifiableList(resourceRefs); 68 | } 69 | 70 | @Override 71 | public String getHost() { 72 | return host; 73 | } 74 | 75 | @Override 76 | public int getPort() { 77 | return port; 78 | } 79 | 80 | @Override 81 | public String getUsername() { 82 | return this.user; 83 | } 84 | 85 | @Override 86 | public String getPassword() { 87 | return this.password; 88 | } 89 | 90 | public void setUser(String user) { 91 | this.user = user; 92 | } 93 | 94 | public void setPassword(String password) { 95 | this.password = password; 96 | } 97 | 98 | public void setHost(String host) { 99 | this.host = host; 100 | } 101 | 102 | public void setPort(int port) { 103 | this.port = port; 104 | } 105 | 106 | public void setSchedulerThreads(int schedulerThreads) { 107 | this.schedulerThreads = schedulerThreads; 108 | } 109 | 110 | @Override 111 | public int getSchedulerThreads() { 112 | return schedulerThreads; 113 | } 114 | 115 | @Override 116 | public String getStorageUrl() { 117 | return this.storageUrl; 118 | } 119 | 120 | @Override 121 | public String getStorageUser() { 122 | return storageUser; 123 | } 124 | 125 | @Override 126 | public String getStoragePassword() { 127 | return storagePassword; 128 | } 129 | 130 | @Override 131 | public String getStorageDBName() { 132 | return storageDb; 133 | } 134 | 135 | 136 | @Override 137 | public Storage getStorageAdapter() { 138 | return storageAdapter; 139 | } 140 | 141 | public void setStorageAdapter(Storage storageAdapter) { 142 | this.storageAdapter = storageAdapter; 143 | } 144 | 145 | public void setStorageUrl(String storageUrl) { 146 | this.storageUrl = storageUrl; 147 | } 148 | 149 | public void setStorageUser(String storageUser) { 150 | this.storageUser = storageUser; 151 | } 152 | 153 | public void setStoragePassword(String storagePassword) { 154 | this.storagePassword = storagePassword; 155 | } 156 | 157 | public void setStorageDb(String storageDb) { 158 | this.storageDb = storageDb; 159 | } 160 | 161 | public void addResourceRef(ResourceRef ref) { 162 | resourceRefs.add(ref); 163 | } 164 | 165 | public String getStorageDb() { 166 | return storageDb; 167 | } 168 | 169 | public String getStorageToken() { 170 | return storageToken; 171 | } 172 | 173 | public void setStorageToken(String storageToken) { 174 | this.storageToken = storageToken; 175 | } 176 | 177 | public String getUser() { 178 | return user; 179 | } 180 | 181 | public Diagnostics getDiagnostics() { 182 | return diagnostics; 183 | } 184 | 185 | public void setDiagnostics(Diagnostics diagnostics) { 186 | this.diagnostics = diagnostics; 187 | } 188 | } 189 | 190 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/config/Interval.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.config; 23 | 24 | import java.util.concurrent.TimeUnit; 25 | 26 | import static java.util.concurrent.TimeUnit.*; 27 | 28 | /** 29 | * @author Harald Pehl 30 | */ 31 | public class Interval{ 32 | 33 | public final static Interval EACH_SECOND = new Interval(1, SECONDS); 34 | public final static Interval TWENTY_SECONDS = new Interval(20, SECONDS); 35 | public final static Interval EACH_MINUTE = new Interval(1, MINUTES); 36 | public final static Interval TWENTY_MINUTES = new Interval(20, MINUTES); 37 | public final static Interval EACH_HOUR = new Interval(1, HOURS); 38 | public final static Interval FOUR_HOURS = new Interval(4, HOURS); 39 | public final static Interval EACH_DAY = new Interval(24, HOURS); 40 | 41 | private final int val; 42 | private final TimeUnit unit; 43 | 44 | public Interval(int val, TimeUnit unit) { 45 | this.val = val; 46 | this.unit = unit; 47 | } 48 | 49 | public long millis() { 50 | return MILLISECONDS.convert(val, unit); 51 | } 52 | 53 | public int getVal() { 54 | return val; 55 | } 56 | 57 | public TimeUnit getUnit() { 58 | return unit; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/config/ResourceRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.config; 23 | 24 | /** 25 | * A resource reference that is to be monitored. 26 | * 27 | * @author Harald Pehl 28 | */ 29 | public class ResourceRef { 30 | 31 | private final String address; 32 | private final String attribute; 33 | private final Interval interval; 34 | 35 | public ResourceRef(final String address, final String attribute, final Interval interval) { 36 | this.address = address; 37 | this.attribute = attribute; 38 | this.interval = interval; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "Task(" + address + ":" + attribute + ", " + interval + ")"; 44 | } 45 | 46 | public String getAddress() { 47 | return address; 48 | } 49 | 50 | public String getAttribute() { 51 | return attribute; 52 | } 53 | 54 | public Interval getInterval() { 55 | return interval; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/diagnose/Diagnostics.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.diagnose; 2 | 3 | import com.codahale.metrics.Counter; 4 | import com.codahale.metrics.Meter; 5 | import com.codahale.metrics.Timer; 6 | 7 | /** 8 | * @author Heiko Braun 9 | * @since 13/10/14 10 | */ 11 | public interface Diagnostics { 12 | Timer getRequestTimer(); 13 | Meter getErrorRate(); 14 | Meter getDelayedRate(); 15 | 16 | Meter getStorageErrorRate(); 17 | Counter getStorageBufferSize(); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/diagnose/StorageReporter.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.diagnose; 2 | 3 | import com.codahale.metrics.Clock; 4 | import com.codahale.metrics.Counter; 5 | import com.codahale.metrics.Gauge; 6 | import com.codahale.metrics.Histogram; 7 | import com.codahale.metrics.Meter; 8 | import com.codahale.metrics.MetricFilter; 9 | import com.codahale.metrics.MetricRegistry; 10 | import com.codahale.metrics.ScheduledReporter; 11 | import com.codahale.metrics.Timer; 12 | import org.wildfly.metrics.scheduler.config.Address; 13 | import org.wildfly.metrics.scheduler.config.Interval; 14 | import org.wildfly.metrics.scheduler.polling.Task; 15 | import org.wildfly.metrics.scheduler.storage.DataPoint; 16 | import org.wildfly.metrics.scheduler.storage.StorageAdapter; 17 | 18 | import java.io.PrintStream; 19 | import java.text.DateFormat; 20 | import java.util.HashSet; 21 | import java.util.Locale; 22 | import java.util.Map; 23 | import java.util.Set; 24 | import java.util.SortedMap; 25 | import java.util.TimeZone; 26 | import java.util.concurrent.TimeUnit; 27 | 28 | /** 29 | * @author Heiko Braun 30 | * @since 14/10/14 31 | */ 32 | public class StorageReporter extends ScheduledReporter { 33 | 34 | private static StorageAdapter storageAdapter; 35 | private final Locale locale; 36 | private final Clock clock; 37 | private final DateFormat dateFormat; 38 | 39 | private StorageReporter(MetricRegistry registry, 40 | Locale locale, 41 | Clock clock, 42 | TimeZone timeZone, 43 | TimeUnit rateUnit, 44 | TimeUnit durationUnit, 45 | MetricFilter filter, StorageAdapter storageAdapter) { 46 | super(registry, "storage-reporter", filter, rateUnit, durationUnit); 47 | this.locale = locale; 48 | this.clock = clock; 49 | this.storageAdapter = storageAdapter; 50 | this.dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, 51 | DateFormat.MEDIUM, 52 | locale); 53 | dateFormat.setTimeZone(timeZone); 54 | } 55 | 56 | 57 | @Override 58 | public void report( 59 | SortedMap gauges, 60 | SortedMap counters, 61 | SortedMap histograms, 62 | SortedMap meters, 63 | SortedMap timers) { 64 | 65 | if (!gauges.isEmpty()) { 66 | 67 | Set samples = new HashSet<>(gauges.size()); 68 | for (Map.Entry entry : gauges.entrySet()) { 69 | Gauge gauge = entry.getValue(); 70 | 71 | samples.add( 72 | new DataPoint( 73 | new Task("foo", "bar", Address.apply("service=metric-scheduler"), entry.getKey(), null, Interval.EACH_SECOND), 74 | gauge.getValue() 75 | ) 76 | ); 77 | } 78 | storageAdapter.store(samples); 79 | } 80 | 81 | if (!counters.isEmpty()) { 82 | 83 | Set samples = new HashSet<>(counters.size()); 84 | for (Map.Entry entry : counters.entrySet()) { 85 | samples.add( 86 | new DataPoint( 87 | new Task("foo", "bar", Address.apply("service=metric-scheduler"), entry.getKey(), null, Interval.EACH_SECOND), 88 | entry.getValue().getCount() 89 | ) 90 | ); 91 | } 92 | 93 | storageAdapter.store(samples); 94 | 95 | } 96 | 97 | /*if (!histograms.isEmpty()) { 98 | 99 | Set samples = new HashSet<>(histograms.size()); 100 | for (Map.Entry entry : histograms.entrySet()) { 101 | Histogram hist = entry.getValue(); 102 | samples.add( 103 | new Sample( 104 | new Task(Address.apply("service=metric-scheduler"), entry.getKey(), null, Interval.EACH_SECOND), 105 | 0 // TODO 106 | ) 107 | ); 108 | } 109 | storageAdapter.store(samples); 110 | }*/ 111 | 112 | if (!meters.isEmpty()) { 113 | 114 | Set samples = new HashSet<>(meters.size()); 115 | for (Map.Entry entry : meters.entrySet()) { 116 | Meter meter = entry.getValue(); 117 | samples.add( 118 | new DataPoint( 119 | new Task("foo", "bar", Address.apply("service=metric-scheduler"), entry.getKey(), null, Interval.EACH_SECOND), 120 | meter.getOneMinuteRate() 121 | ) 122 | ); 123 | } 124 | storageAdapter.store(samples); 125 | } 126 | 127 | if (!timers.isEmpty()) { 128 | 129 | Set samples = new HashSet<>(timers.size()); 130 | 131 | for (Map.Entry entry : timers.entrySet()) { 132 | Timer timer = entry.getValue(); 133 | 134 | samples.add( 135 | new DataPoint( 136 | new Task("foo", "bar", Address.apply("service=metric-scheduler"), entry.getKey(), null, Interval.EACH_SECOND), 137 | timer.getSnapshot().get75thPercentile() 138 | ) 139 | ); 140 | } 141 | 142 | storageAdapter.store(samples); 143 | } 144 | 145 | } 146 | 147 | public static Builder forRegistry(MetricRegistry registry, StorageAdapter storageAdapter) { 148 | return new Builder(registry, storageAdapter); 149 | } 150 | 151 | public static class Builder { 152 | private final MetricRegistry registry; 153 | private final StorageAdapter storageAdapter; 154 | private PrintStream output; 155 | private Locale locale; 156 | private Clock clock; 157 | private TimeZone timeZone; 158 | private TimeUnit rateUnit; 159 | private TimeUnit durationUnit; 160 | private MetricFilter filter; 161 | 162 | private Builder(MetricRegistry registry, StorageAdapter storageAdapter) { 163 | this.registry = registry; 164 | this.storageAdapter = storageAdapter; 165 | this.locale = Locale.getDefault(); 166 | this.clock = Clock.defaultClock(); 167 | this.timeZone = TimeZone.getDefault(); 168 | this.rateUnit = TimeUnit.SECONDS; 169 | this.durationUnit = TimeUnit.MILLISECONDS; 170 | this.filter = MetricFilter.ALL; 171 | } 172 | 173 | /** 174 | * Write to the given {@link PrintStream}. 175 | * 176 | * @param output a {@link PrintStream} instance. 177 | * @return {@code this} 178 | */ 179 | public Builder outputTo(PrintStream output) { 180 | this.output = output; 181 | return this; 182 | } 183 | 184 | /** 185 | * Format numbers for the given {@link Locale}. 186 | * 187 | * @param locale a {@link Locale} 188 | * @return {@code this} 189 | */ 190 | public Builder formattedFor(Locale locale) { 191 | this.locale = locale; 192 | return this; 193 | } 194 | 195 | /** 196 | * Use the given {@link Clock} instance for the time. 197 | * 198 | * @param clock a {@link Clock} instance 199 | * @return {@code this} 200 | */ 201 | public Builder withClock(Clock clock) { 202 | this.clock = clock; 203 | return this; 204 | } 205 | 206 | /** 207 | * Use the given {@link TimeZone} for the time. 208 | * 209 | * @param timeZone a {@link TimeZone} 210 | * @return {@code this} 211 | */ 212 | public Builder formattedFor(TimeZone timeZone) { 213 | this.timeZone = timeZone; 214 | return this; 215 | } 216 | 217 | /** 218 | * Convert rates to the given time unit. 219 | * 220 | * @param rateUnit a unit of time 221 | * @return {@code this} 222 | */ 223 | public Builder convertRatesTo(TimeUnit rateUnit) { 224 | this.rateUnit = rateUnit; 225 | return this; 226 | } 227 | 228 | /** 229 | * Convert durations to the given time unit. 230 | * 231 | * @param durationUnit a unit of time 232 | * @return {@code this} 233 | */ 234 | public Builder convertDurationsTo(TimeUnit durationUnit) { 235 | this.durationUnit = durationUnit; 236 | return this; 237 | } 238 | 239 | /** 240 | * Only report metrics which match the given filter. 241 | * 242 | * @param filter a {@link MetricFilter} 243 | * @return {@code this} 244 | */ 245 | public Builder filter(MetricFilter filter) { 246 | this.filter = filter; 247 | return this; 248 | } 249 | 250 | public StorageReporter build() { 251 | return new StorageReporter(registry, 252 | locale, 253 | clock, 254 | timeZone, 255 | rateUnit, 256 | durationUnit, 257 | filter, storageAdapter 258 | ); 259 | } 260 | } 261 | 262 | } 263 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/AbstractScheduler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.polling; 23 | 24 | /** 25 | * @author Harald Pehl 26 | */ 27 | public abstract class AbstractScheduler implements Scheduler { 28 | 29 | private State state = State.STOPPED; 30 | 31 | protected void pushState(State state) { 32 | this.state = state; 33 | } 34 | 35 | protected void verifyState(State state) throws IllegalStateException { 36 | if (this.state != state) { 37 | throw new IllegalStateException("Expected state " + state + ", but got " + this.state); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/ClientFactoryImpl.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.polling; 2 | 3 | import org.jboss.as.controller.client.ModelControllerClient; 4 | import org.wildfly.metrics.scheduler.ModelControllerClientFactory; 5 | 6 | import javax.security.auth.callback.Callback; 7 | import javax.security.auth.callback.CallbackHandler; 8 | import javax.security.auth.callback.NameCallback; 9 | import javax.security.auth.callback.PasswordCallback; 10 | import javax.security.auth.callback.UnsupportedCallbackException; 11 | import javax.security.sasl.RealmCallback; 12 | import java.io.IOException; 13 | import java.net.InetAddress; 14 | import java.net.UnknownHostException; 15 | 16 | /** 17 | * @author Heiko Braun 18 | * @since 17/10/14 19 | */ 20 | public class ClientFactoryImpl implements ModelControllerClientFactory { 21 | 22 | private String host; 23 | private int port; 24 | private String username; 25 | private String password; 26 | 27 | public ClientFactoryImpl(String host, int port, String username, String password) { 28 | this.host = host; 29 | this.port = port; 30 | this.username = username; 31 | this.password = password; 32 | } 33 | 34 | @Override 35 | public ModelControllerClient createClient() { 36 | 37 | final CallbackHandler callbackHandler = new CallbackHandler() { 38 | 39 | public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { 40 | for (Callback current : callbacks) { 41 | if (current instanceof NameCallback) { 42 | NameCallback ncb = (NameCallback) current; 43 | ncb.setName(username); 44 | } else if (current instanceof PasswordCallback) { 45 | PasswordCallback pcb = (PasswordCallback) current; 46 | pcb.setPassword(password.toCharArray()); 47 | } else if (current instanceof RealmCallback) { 48 | RealmCallback rcb = (RealmCallback) current; 49 | rcb.setText(rcb.getDefaultText()); 50 | } else { 51 | throw new UnsupportedCallbackException(current); 52 | } 53 | } 54 | } 55 | }; 56 | 57 | try { 58 | return ModelControllerClient.Factory.create(InetAddress.getByName(host), port, callbackHandler); 59 | } catch (UnknownHostException e) { 60 | throw new RuntimeException("Failed ot create controller client", e); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/IntervalBasedScheduler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.polling; 23 | 24 | import com.codahale.metrics.Timer; 25 | import org.jboss.as.controller.client.ModelControllerClient; 26 | import org.jboss.dmr.ModelNode; 27 | import org.jboss.dmr.Property; 28 | import org.rhq.wfly.monitor.extension.MonitorLogger; 29 | import org.wildfly.metrics.scheduler.ModelControllerClientFactory; 30 | import org.wildfly.metrics.scheduler.SchedulerLogger; 31 | import org.wildfly.metrics.scheduler.diagnose.Diagnostics; 32 | import org.wildfly.metrics.scheduler.storage.DataPoint; 33 | 34 | import java.io.IOException; 35 | import java.util.LinkedList; 36 | import java.util.List; 37 | import java.util.concurrent.ConcurrentLinkedQueue; 38 | import java.util.concurrent.Executors; 39 | import java.util.concurrent.ScheduledExecutorService; 40 | import java.util.concurrent.ScheduledFuture; 41 | import java.util.concurrent.ThreadFactory; 42 | import java.util.concurrent.TimeUnit; 43 | 44 | import static java.util.concurrent.TimeUnit.MILLISECONDS; 45 | import static org.wildfly.metrics.scheduler.polling.Scheduler.State.RUNNING; 46 | import static org.wildfly.metrics.scheduler.polling.Scheduler.State.STOPPED; 47 | 48 | /** 49 | * @author Harald Pehl 50 | * @author Heiko Braun 51 | */ 52 | public class IntervalBasedScheduler extends AbstractScheduler { 53 | 54 | private final ScheduledExecutorService executorService; 55 | private final List jobs; 56 | private final int poolSize; 57 | 58 | private final ModelControllerClientFactory clientFactory; 59 | private final Diagnostics monitor; 60 | 61 | private ConcurrentLinkedQueue connectionPool = new ConcurrentLinkedQueue<>(); 62 | 63 | public IntervalBasedScheduler(ModelControllerClientFactory clientFactory, Diagnostics monitor, final int poolSize) { 64 | this.clientFactory = clientFactory; 65 | this.monitor = monitor; 66 | this.poolSize = poolSize; 67 | 68 | this.executorService = Executors.newScheduledThreadPool(poolSize, new ThreadFactory() { 69 | @Override 70 | public Thread newThread(Runnable r) { 71 | SchedulerLogger.LOGGER.debug("Creating new executor thread"); 72 | return new Thread(r); 73 | } 74 | }); 75 | 76 | this.jobs = new LinkedList<>(); 77 | 78 | } 79 | 80 | @Override 81 | public void schedule(List tasks, final CompletionHandler completionHandler) { 82 | verifyState(STOPPED); 83 | 84 | // optimize task groups 85 | List groups = new IntervalGrouping().apply(tasks); 86 | 87 | SchedulerLogger.LOGGER.infof("Number of tasks: %s", tasks.size()); 88 | SchedulerLogger.LOGGER.infof("Number of task groups: %s", groups.size()); 89 | 90 | // populate connection pool 91 | for (int i = 0; i < poolSize; i++) { 92 | try { 93 | connectionPool.add( 94 | clientFactory.createClient() 95 | ); 96 | } catch (Throwable e) { 97 | e.printStackTrace(); 98 | } 99 | } 100 | 101 | // schedule IO 102 | for (TaskGroup group : groups) { 103 | jobs.add( 104 | 105 | // schedule tasks 106 | executorService.scheduleWithFixedDelay( 107 | new IO(group, completionHandler), 108 | group.getOffsetMillis(), group.getInterval().millis(), 109 | MILLISECONDS 110 | ) 111 | ); 112 | } 113 | 114 | pushState(RUNNING); 115 | } 116 | 117 | @Override 118 | public void shutdown() { 119 | verifyState(RUNNING); 120 | 121 | 122 | try { 123 | for (ScheduledFuture job : jobs) { 124 | job.cancel(false); 125 | } 126 | executorService.shutdown(); 127 | executorService.awaitTermination(5, TimeUnit.SECONDS); 128 | 129 | } catch (InterruptedException e) { 130 | e.printStackTrace(); 131 | } finally { 132 | 133 | // cleanup pool 134 | for (ModelControllerClient client : connectionPool) { 135 | try { 136 | client.close(); 137 | } catch (IOException e) { 138 | e.printStackTrace(); 139 | } 140 | }; 141 | 142 | pushState(STOPPED); 143 | } 144 | } 145 | 146 | private class IO implements Runnable { 147 | 148 | private static final String OUTCOME = "outcome"; 149 | private static final String RESULT = "result"; 150 | private static final String FAILURE_DESCRIPTION = "failure-description"; 151 | private static final String SUCCESS = "success"; 152 | 153 | private final TaskGroup group; 154 | private final CompletionHandler completionHandler; 155 | private final ModelNode operation; 156 | 157 | private IO(TaskGroup group, CompletionHandler completionHandler) { 158 | this.group = group; 159 | this.completionHandler = completionHandler; 160 | 161 | // for the IO lifetime the operation is immutable and can be re-used 162 | this.operation = new ReadAttributeOperationBuilder().createOperation(group); 163 | } 164 | 165 | @Override 166 | public void run() { 167 | 168 | if(connectionPool.isEmpty()) 169 | throw new IllegalStateException("Connection pool expired!"); 170 | final ModelControllerClient client = connectionPool.poll(); 171 | 172 | try { 173 | 174 | Timer.Context requestContext = monitor.getRequestTimer().time(); 175 | 176 | // execute request 177 | ModelNode response = client.execute(operation); 178 | 179 | long durationMs = requestContext.stop() / 1000000; 180 | 181 | String outcome = response.get(OUTCOME).asString(); 182 | if (SUCCESS.equals(outcome)) 183 | { 184 | 185 | if (durationMs > group.getInterval().millis()) { 186 | monitor.getDelayedRate().mark(1); 187 | } 188 | 189 | List steps = response.get(RESULT).asPropertyList(); 190 | assert steps.size() == group.size() : "group structure doesn't match actual response structure"; 191 | 192 | int i=0; 193 | for (Property step : steps) { 194 | Task task = group.getTask(i); 195 | 196 | // deconstruct model node 197 | ModelNode data = step.getValue(); 198 | Double value = null; 199 | if(task.getSubref()!=null) 200 | { 201 | value = data.get(RESULT).get(task.getSubref()).asDouble(); 202 | } 203 | else 204 | { 205 | value = data.get(RESULT).asDouble(); 206 | } 207 | 208 | completionHandler.onCompleted(new DataPoint(task, value)); 209 | i++; 210 | } 211 | 212 | 213 | } else { 214 | monitor.getErrorRate().mark(1); 215 | completionHandler.onFailed(new RuntimeException(response.get(FAILURE_DESCRIPTION).asString())); 216 | } 217 | 218 | } catch (Throwable e) { 219 | monitor.getErrorRate().mark(1); 220 | completionHandler.onFailed(e); 221 | } finally { 222 | 223 | // return to pool 224 | connectionPool.add(client); 225 | 226 | } 227 | } 228 | 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/IntervalGrouping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.polling; 23 | 24 | import org.wildfly.metrics.scheduler.config.Interval; 25 | 26 | import java.util.ArrayList; 27 | import java.util.Collections; 28 | import java.util.Comparator; 29 | import java.util.List; 30 | 31 | /** 32 | * @author Harald Pehl 33 | */ 34 | public class IntervalGrouping implements TaskGrouping { 35 | 36 | @Override 37 | public List apply(final List tasks) { 38 | 39 | Collections.sort(tasks, new Comparator() { 40 | @Override 41 | public int compare(Task t1, Task t2) { 42 | return new Long(t1.getInterval().millis()).compareTo(t2.getInterval().millis()); 43 | } 44 | }); 45 | 46 | 47 | List groups = new ArrayList<>(); 48 | Interval interval = tasks.get(0).getInterval(); 49 | TaskGroup taskGroup = new TaskGroup(interval); 50 | groups.add(taskGroup); 51 | 52 | for (Task task : tasks) { 53 | 54 | if(!task.getInterval().equals(interval)) { 55 | // new group 56 | interval = task.getInterval(); 57 | groups.add(new TaskGroup(task.getInterval())); 58 | } 59 | 60 | groups.get(groups.size()-1).addTask(task); 61 | } 62 | 63 | return groups; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/OperationBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.polling; 23 | 24 | 25 | import org.jboss.dmr.ModelNode; 26 | 27 | /** 28 | * An interface to create operations ({@link ModelNode}'s) from {@link TaskGroup}s. 29 | * 30 | * @author Harald Pehl 31 | */ 32 | public interface OperationBuilder { 33 | 34 | ModelNode createOperation(TaskGroup group); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/ReadAttributeOperationBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.polling; 23 | 24 | import org.jboss.dmr.ModelNode; 25 | import org.wildfly.metrics.scheduler.config.Address; 26 | 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | /** 31 | * Creates a {@code read-attribute} operation of the given {@link TaskGroup}. 32 | * 33 | * @author Harald Pehl 34 | */ 35 | public class ReadAttributeOperationBuilder implements OperationBuilder { 36 | 37 | @Override 38 | public ModelNode createOperation(final TaskGroup group) { 39 | 40 | if (group.isEmpty()) { 41 | throw new IllegalArgumentException("Empty groups are not allowed"); 42 | } 43 | 44 | ModelNode comp = new ModelNode(); 45 | List steps = new ArrayList<>(); 46 | comp.get("address").setEmptyList(); 47 | comp.get("operation").set("composite"); 48 | for (Task task : group) { 49 | steps.add(readAttribute(task)); 50 | } 51 | comp.get("steps").set(steps); 52 | 53 | return comp; 54 | 55 | } 56 | 57 | private ModelNode readAttribute(Task task) { 58 | ModelNode node = new ModelNode(); 59 | Address address = task.getAddress(); 60 | for (Address.Tuple tuple : address) { 61 | node.get("address").add(tuple.getKey(), tuple.getValue()); 62 | } 63 | node.get("operation").set("read-attribute"); 64 | node.get("name").set(task.getAttribute()); 65 | return node; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/Scheduler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.polling; 23 | 24 | import org.wildfly.metrics.scheduler.storage.DataPoint; 25 | 26 | import java.util.List; 27 | 28 | /** 29 | * Performs the actual work collecting the data from the monitored resources. 30 | * Used by the main {@link org.wildfly.metrics.scheduler.Service} 31 | * 32 | * @author Harald Pehl 33 | */ 34 | public interface Scheduler { 35 | 36 | public enum State {RUNNING, STOPPED} 37 | 38 | void schedule(List operations, CompletionHandler completionHandler); 39 | 40 | void shutdown(); 41 | 42 | /** 43 | * Callback for completed tasks 44 | */ 45 | interface CompletionHandler { 46 | void onCompleted(DataPoint sample); 47 | void onFailed(Throwable e); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/Task.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.polling; 2 | 3 | import org.wildfly.metrics.scheduler.config.Address; 4 | import org.wildfly.metrics.scheduler.config.Interval; 5 | 6 | /** 7 | * Represents a monitoring task. Represents and absolute address within a domain. 8 | * 9 | * @author Heiko Braun 10 | * @since 10/10/14 11 | */ 12 | public class Task { 13 | 14 | private final String host; 15 | private final String server; 16 | private final Address address; 17 | private final String attribute; 18 | private final String subref; 19 | private final Interval interval; 20 | 21 | public Task( 22 | String host, String server, 23 | Address address, 24 | String attribute, 25 | String subref, 26 | Interval interval 27 | ) { 28 | this.host = host; 29 | this.server = server; 30 | this.address = address; 31 | this.attribute = attribute; 32 | this.subref = subref; 33 | this.interval = interval; 34 | } 35 | 36 | public Address getAddress() { 37 | return address; 38 | } 39 | 40 | public String getAttribute() { 41 | return attribute; 42 | } 43 | 44 | public Interval getInterval() { 45 | return interval; 46 | } 47 | 48 | public String getSubref() { 49 | return subref; 50 | } 51 | 52 | public String getHost() { 53 | return host; 54 | } 55 | 56 | public String getServer() { 57 | return server; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return "Task{" + 63 | "address=" + address + 64 | ", attribute='" + attribute + '\'' + 65 | '}'; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/TaskGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.polling; 23 | 24 | import com.google.common.collect.Iterators; 25 | import org.wildfly.metrics.scheduler.config.Interval; 26 | 27 | import java.util.Collection; 28 | import java.util.Iterator; 29 | import java.util.LinkedList; 30 | import java.util.UUID; 31 | 32 | /** 33 | * @author Harald Pehl 34 | */ 35 | public class TaskGroup implements Iterable { 36 | 37 | private final String id; // to uniquely reference this group 38 | private final Interval interval; // impacts thread scheduling 39 | private final long offsetMillis; 40 | private final LinkedList tasks; 41 | 42 | public TaskGroup(final Interval interval) { 43 | this.offsetMillis = 0; 44 | this.id = UUID.randomUUID().toString(); 45 | this.interval = interval; 46 | this.tasks = new LinkedList<>(); 47 | } 48 | 49 | public void addTask(Task task) { 50 | verifyInterval(task); 51 | tasks.add(task); 52 | } 53 | 54 | public boolean addTasks(final Collection collection) { 55 | for (Task t: collection) { 56 | verifyInterval(t); 57 | } 58 | return tasks.addAll(collection); 59 | } 60 | 61 | private void verifyInterval(final Task task) { 62 | if (task.getInterval() != interval) { 63 | throw new IllegalArgumentException("Wrong interval: Expected " + interval + ", but got " + task.getInterval()); 64 | } 65 | } 66 | 67 | public int size() {return tasks.size();} 68 | 69 | public boolean isEmpty() {return tasks.isEmpty();} 70 | 71 | @Override 72 | public Iterator iterator() { 73 | return Iterators.unmodifiableIterator(tasks.iterator()); 74 | } 75 | 76 | public String getId() { 77 | return id; 78 | } 79 | 80 | public Interval getInterval() { 81 | return interval; 82 | } 83 | 84 | public long getOffsetMillis() { 85 | return offsetMillis; 86 | } 87 | 88 | public Task getTask(int i) { 89 | return tasks.get(i); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/polling/TaskGrouping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2010, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | package org.wildfly.metrics.scheduler.polling; 23 | 24 | import java.util.List; 25 | 26 | /** 27 | * @author Harald Pehl 28 | */ 29 | public interface TaskGrouping { 30 | 31 | List apply(List tasks); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/storage/BufferedStorageDispatcher.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.storage; 2 | 3 | import org.wildfly.metrics.scheduler.diagnose.Diagnostics; 4 | import org.wildfly.metrics.scheduler.polling.Scheduler; 5 | 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | import java.util.concurrent.ArrayBlockingQueue; 9 | import java.util.concurrent.BlockingQueue; 10 | 11 | /** 12 | * @author Heiko Braun 13 | * @since 13/10/14 14 | */ 15 | public class BufferedStorageDispatcher implements Scheduler.CompletionHandler { 16 | 17 | private static final int MAX_BATCH_SIZE = 24; 18 | private static final int BUFFER_SIZE = 100; 19 | private final StorageAdapter storageAdapter; 20 | private final Diagnostics diagnostics; 21 | private final BlockingQueue queue; 22 | private final Worker worker; 23 | 24 | public BufferedStorageDispatcher(StorageAdapter storageAdapter, Diagnostics diagnostics) { 25 | this.storageAdapter = storageAdapter; 26 | this.diagnostics = diagnostics; 27 | this.queue = new ArrayBlockingQueue(BUFFER_SIZE); 28 | this.worker = new Worker(queue); 29 | } 30 | 31 | public void start() { 32 | worker.start(); 33 | } 34 | 35 | public void shutdown() { 36 | worker.setKeepRunnig(false); 37 | } 38 | 39 | @Override 40 | public void onCompleted(DataPoint sample) { 41 | if(queue.remainingCapacity()>0) { 42 | //System.out.println(sample.getTask().getAttribute()+" > "+sample.getValue()); 43 | diagnostics.getStorageBufferSize().inc(); 44 | queue.add(sample); 45 | } 46 | else { 47 | throw new RuntimeException("buffer capacity exceeded"); 48 | } 49 | } 50 | 51 | @Override 52 | public void onFailed(Throwable e) { 53 | e.printStackTrace(); 54 | } 55 | 56 | public class Worker extends Thread { 57 | private final BlockingQueue queue; 58 | private boolean keepRunning = true; 59 | 60 | public Worker(BlockingQueue queue) { 61 | this.queue = queue; 62 | } 63 | 64 | public void run() { 65 | try { 66 | while ( keepRunning ) { 67 | 68 | // batch processing 69 | DataPoint sample = queue.take(); 70 | Set samples = new HashSet<>(); 71 | queue.drainTo(samples, MAX_BATCH_SIZE); 72 | samples.add(sample); 73 | 74 | diagnostics.getStorageBufferSize().dec(samples.size()); 75 | 76 | // dispatch 77 | storageAdapter.store(samples); 78 | } 79 | } 80 | catch ( InterruptedException ie ) { 81 | // just terminate 82 | } 83 | } 84 | 85 | public void setKeepRunnig(boolean keepRunning) { 86 | this.keepRunning = keepRunning; 87 | } 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/storage/DataPoint.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.storage; 2 | 3 | import org.wildfly.metrics.scheduler.polling.Task; 4 | 5 | /** 6 | * @author Heiko Braun 7 | * @since 13/10/14 8 | */ 9 | public final class DataPoint { 10 | private Task task; 11 | private long timestamp; 12 | private double value; 13 | 14 | public DataPoint(Task task, double value) { 15 | this.task = task; 16 | this.timestamp = System.currentTimeMillis(); 17 | this.value = value; 18 | } 19 | 20 | public Task getTask() { 21 | return task; 22 | } 23 | 24 | public long getTimestamp() { 25 | return timestamp; 26 | } 27 | 28 | public double getValue() { 29 | return value; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/storage/DefaultKeyResolution.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.storage; 2 | 3 | import org.wildfly.metrics.scheduler.polling.Task; 4 | 5 | /** 6 | * Resolve data input attributes to final metric (storage) names. 7 | * 8 | * @author Heiko Braun 9 | * @since 24/10/14 10 | */ 11 | public class DefaultKeyResolution implements KeyResolution { 12 | @Override 13 | public String resolve(Task task) { 14 | if(task.getHost()!=null && !task.getHost().equals("")) 15 | { 16 | // domain 17 | return task.getHost()+"."+task.getServer()+"."+task.getAttribute(); 18 | } 19 | else 20 | { 21 | // standalone 22 | return task.getServer()+"."+task.getAttribute(); 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/storage/InfluxStorageAdapter.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.storage; 2 | 3 | import org.influxdb.InfluxDB; 4 | import org.influxdb.InfluxDBFactory; 5 | import org.influxdb.dto.Serie; 6 | import org.wildfly.metrics.scheduler.config.Configuration; 7 | import org.wildfly.metrics.scheduler.diagnose.Diagnostics; 8 | import org.wildfly.metrics.scheduler.polling.Task; 9 | 10 | import java.util.Set; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | /** 14 | * Pushes the data to Influx. 15 | * 16 | * @author Heiko Braun 17 | * @since 13/10/14 18 | */ 19 | public class InfluxStorageAdapter implements StorageAdapter { 20 | 21 | private InfluxDB influxDB; 22 | private String dbName; 23 | private Diagnostics diagnostics; 24 | private Configuration config; 25 | private DefaultKeyResolution keyResolution; 26 | 27 | @Override 28 | public void setConfiguration(Configuration config) { 29 | this.config = config; 30 | this.influxDB = InfluxDBFactory.connect( 31 | config.getStorageUrl(), 32 | config.getStorageUser(), 33 | config.getStoragePassword() 34 | ); 35 | this.dbName = config.getStorageDBName(); 36 | 37 | this.keyResolution = new DefaultKeyResolution(); 38 | } 39 | 40 | @Override 41 | public void setDiagnostics(Diagnostics diag) { 42 | this.diagnostics = diag; 43 | } 44 | 45 | @Override 46 | public void store(Set datapoints) { 47 | 48 | try { 49 | 50 | Serie[] series = new Serie[datapoints.size()]; 51 | int i=0; 52 | for (DataPoint datapoint : datapoints) { 53 | 54 | Task task = datapoint.getTask(); 55 | String key = keyResolution.resolve(task); 56 | Serie dataPoint = new Serie.Builder(key) 57 | .columns("datapoint") 58 | .values(datapoint.getValue()) 59 | .build(); 60 | 61 | series[i] = dataPoint; 62 | i++; 63 | } 64 | 65 | this.influxDB.write(this.dbName, TimeUnit.MILLISECONDS, series); 66 | 67 | } catch (Throwable t) { 68 | diagnostics.getStorageErrorRate().mark(1); 69 | t.printStackTrace(); 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/storage/KeyResolution.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.storage; 2 | 3 | import org.wildfly.metrics.scheduler.polling.Task; 4 | 5 | /** 6 | * @author Heiko Braun 7 | * @since 24/10/14 8 | */ 9 | public interface KeyResolution { 10 | String resolve(Task task); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/storage/RHQStorageAdapter.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.storage; 2 | 3 | import org.apache.http.HttpResponse; 4 | import org.apache.http.StatusLine; 5 | import org.apache.http.client.HttpClient; 6 | import org.apache.http.client.methods.HttpPost; 7 | import org.apache.http.entity.StringEntity; 8 | import org.apache.http.impl.client.DefaultHttpClient; 9 | import org.rhq.metrics.client.common.Batcher; 10 | import org.rhq.metrics.client.common.SingleMetric; 11 | import org.wildfly.metrics.scheduler.config.Configuration; 12 | import org.wildfly.metrics.scheduler.diagnose.Diagnostics; 13 | import org.wildfly.metrics.scheduler.polling.Task; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Set; 18 | 19 | /** 20 | * Pushes the data to RHQ metrics. 21 | * 22 | * @author Heiko Braun 23 | * @since 13/10/14 24 | */ 25 | public class RHQStorageAdapter implements StorageAdapter { 26 | 27 | private Configuration config; 28 | private Diagnostics diagnostics; 29 | private final HttpClient httpclient; 30 | private final DefaultKeyResolution keyResolution; 31 | 32 | public RHQStorageAdapter() { 33 | this.httpclient = new DefaultHttpClient(); 34 | this.keyResolution = new DefaultKeyResolution(); 35 | } 36 | 37 | @Override 38 | public void setConfiguration(Configuration config) { 39 | this.config = config; 40 | } 41 | 42 | @Override 43 | public void setDiagnostics(Diagnostics diag) { 44 | this.diagnostics = diag; 45 | } 46 | 47 | @Override 48 | public void store(Set datapoints) { 49 | HttpPost post = new HttpPost(config.getStorageUrl()); 50 | try { 51 | List metrics = new ArrayList<>(); 52 | 53 | for (DataPoint datapoint : datapoints) { 54 | Task task = datapoint.getTask(); 55 | String key = keyResolution.resolve(task); 56 | metrics.add(new SingleMetric(key, datapoint.getTimestamp(), datapoint.getValue())); 57 | } 58 | 59 | 60 | // If we have data, send it to the RHQ Metrics server 61 | 62 | if (metrics.size()>0) { 63 | post.setHeader("Content-Type", "application/json;charset=utf-8"); 64 | post.setEntity(new StringEntity(Batcher.metricListToJson(metrics))); 65 | 66 | HttpResponse httpResponse = httpclient.execute(post); 67 | StatusLine statusLine = httpResponse.getStatusLine(); 68 | 69 | if (statusLine.getStatusCode() != 200) { 70 | throw new Exception("HTTP Status "+statusLine.getStatusCode()+": "+statusLine); 71 | } 72 | 73 | 74 | } 75 | } catch (Throwable t) { 76 | t.printStackTrace(); 77 | diagnostics.getStorageErrorRate().mark(1); 78 | } 79 | finally { 80 | post.releaseConnection(); 81 | } 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/wildfly/metrics/scheduler/storage/StorageAdapter.java: -------------------------------------------------------------------------------- 1 | package org.wildfly.metrics.scheduler.storage; 2 | 3 | import org.wildfly.metrics.scheduler.config.Configuration; 4 | import org.wildfly.metrics.scheduler.diagnose.Diagnostics; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * @author Heiko Braun 10 | * @since 10/10/14 11 | */ 12 | public interface StorageAdapter { 13 | void store(Set datapoints); 14 | void setConfiguration(Configuration config); 15 | void setDiagnostics(Diagnostics diag); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org.jboss.as.controller.Extension: -------------------------------------------------------------------------------- 1 | org.rhq.wfly.monitor.extension.SubsystemExtension 2 | -------------------------------------------------------------------------------- /src/main/resources/config/monitor-host.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 82 | 83 | 84 | 85 | 86 | 87 | 94 | 95 | 96 | 98 | 99 | 100 | 101 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /src/main/resources/config/standalone-monitor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 85 | 86 | 87 | 88 | 92 | 93 | 97 | 98 | 102 | 103 | 104 | 105 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 169 | h2 170 | 171 | sa 172 | sa 173 | 174 | 175 | 176 | 177 | org.h2.jdbcx.JdbcDataSource 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | false 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | ${jboss.bind.address:127.0.0.1} 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | -------------------------------------------------------------------------------- /src/main/resources/module/main/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/resources/org/rhq/wfly/monitor/extension/LocalDescriptions.properties: -------------------------------------------------------------------------------- 1 | wildfly-monitor=Monitor subsystem 2 | wildfly-monitor.add=Adds the subsystem 3 | wildfly-monitor.remove=Removes the subsystem 4 | 5 | wildfly-monitor.server-monitor=A server monitor 6 | wildfly-monitor.server-monitor.add=Adds a monitor 7 | wildfly-monitor.server-monitor.remove=Removes a monitor 8 | wildfly-monitor.server-monitor.enabled=Enable monitoring (requires reload/restart) 9 | wildfly-monitor.server-monitor.num-threads=Thread pool size for the scheduler 10 | 11 | wildfly-monitor.storage-adapter=The storage adapter to persist the data points 12 | wildfly-monitor.storage-adapter.add=Adds a storage adapter 13 | wildfly-monitor.storage-adapter.remove=Removes a storage adapter 14 | wildfly-monitor.storage-adapter.url=The url of the remote storage system 15 | wildfly-monitor.storage-adapter.user=Access token of the storage system 16 | wildfly-monitor.storage-adapter.password=Access token of the storage system 17 | wildfly-monitor.storage-adapter.token=Access token of the storage system 18 | wildfly-monitor.storage-adapter.name=Name of the storage adapter type (rhq|influx) 19 | wildfly-monitor.storage-adapter.db=Name of the database to write to 20 | 21 | wildfly-monitor.server-monitor.data-input=Definition of a single resource attribute to monitor 22 | wildfly-monitor.server-monitor.data-input.add=Adds a data input 23 | wildfly-monitor.server-monitor.data-input.remove=Removes a data input 24 | wildfly-monitor.server-monitor.data-input.resource=DMR path of the management resource 25 | wildfly-monitor.server-monitor.data-input.name=(Display) name of the Metric 26 | wildfly-monitor.server-monitor.data-input.attribute=Name of the desired attribute inside the management resource 27 | wildfly-monitor.server-monitor.data-input.seconds=Schedule interval in seconds 28 | wildfly-monitor.server-monitor.data-input.minutes=Schedule interval in minutes 29 | wildfly-monitor.server-monitor.data-input.hours=Schedule interval in hours 30 | 31 | wildfly-monitor.diagnostics=Subsystem diagnostics 32 | wildfly-monitor.diagnostics.add=Adds a diagnostics element 33 | wildfly-monitor.diagnostics.remove=Removes a diagnostics element 34 | wildfly-monitor.diagnostics.enabled=Enables diagnostics reporting 35 | wildfly-monitor.diagnostics.seconds=Report interval in seconds 36 | wildfly-monitor.diagnostics.minutes=Report interval in minutes 37 | 38 | -------------------------------------------------------------------------------- /src/main/resources/schema/wildfly-monitor-subsystem.xsd: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/main/resources/subsystem.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 26 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /src/test/java/org/rhq/wfly/monitor/extension/SubsystemBaseParsingTestCase.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * This is the bare bones test example that tests subsystem 9 | * It does same things that {@link SubsystemParsingTestCase} does but most of internals are already done in AbstractSubsystemBaseTest 10 | * If you need more control over what happens in tests look at {@link SubsystemParsingTestCase} 11 | * @author Tomaz Cerar 12 | */ 13 | public class SubsystemBaseParsingTestCase extends AbstractSubsystemBaseTest { 14 | 15 | public SubsystemBaseParsingTestCase() { 16 | super(SubsystemExtension.SUBSYSTEM_NAME, new SubsystemExtension()); 17 | } 18 | 19 | 20 | @Override 21 | protected String getSubsystemXml() throws IOException { 22 | return readResource("subsystem.xml"); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/org/rhq/wfly/monitor/extension/SubsystemParsingTestCase.java: -------------------------------------------------------------------------------- 1 | package org.rhq.wfly.monitor.extension; 2 | 3 | 4 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD; 5 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; 6 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; 7 | import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM; 8 | 9 | import java.util.List; 10 | 11 | import org.jboss.as.controller.PathAddress; 12 | import org.jboss.as.controller.PathElement; 13 | import org.jboss.as.subsystem.test.KernelServices; 14 | import org.jboss.dmr.ModelNode; 15 | 16 | import org.junit.After; 17 | import org.junit.Assert; 18 | import org.junit.Before; 19 | import org.junit.Test; 20 | 21 | 22 | /** 23 | * Tests all management expects for subsystem, parsing, marshaling, model definition and other 24 | * Here is an example that allows you a fine grained controler over what is tested and how. So it can give you ideas what can be done and tested. 25 | * If you have no need for advanced testing of subsystem you look at {@link SubsystemBaseParsingTestCase} that testes same stuff but most of the code 26 | * is hidden inside of test harness 27 | * 28 | * @author Kabir Khan 29 | */ 30 | public class SubsystemParsingTestCase extends SubsystemBaseParsingTestCase { 31 | 32 | @Override 33 | @Before 34 | public void initializeParser() throws Exception { 35 | super.initializeParser(); 36 | } 37 | 38 | @Override 39 | @After 40 | public void cleanup() throws Exception { 41 | super.cleanup(); 42 | } 43 | /** 44 | * Tests that the xml is parsed into the correct operations 45 | */ 46 | @Test 47 | public void testParseSubsystem() throws Exception { 48 | //Parse the subsystem xml into operations 49 | String subsystemXml = getSubsystemXml(); 50 | List operations = super.parse(subsystemXml); 51 | 52 | ///Check that we have the expected number of operations 53 | Assert.assertEquals(7, operations.size()); 54 | 55 | //Check that each operation has the correct content 56 | ModelNode addSubsystem = operations.get(0); 57 | Assert.assertEquals(ADD, addSubsystem.get(OP).asString()); 58 | PathAddress addr = PathAddress.pathAddress(addSubsystem.get(OP_ADDR)); 59 | Assert.assertEquals(1, addr.size()); 60 | PathElement element = addr.getElement(0); 61 | Assert.assertEquals(SUBSYSTEM, element.getKey()); 62 | Assert.assertEquals(SubsystemExtension.SUBSYSTEM_NAME, element.getValue()); 63 | 64 | } 65 | 66 | /** 67 | * Test that the model created from the xml looks as expected 68 | */ 69 | @Test 70 | public void testInstallIntoController() throws Exception { 71 | //Parse the subsystem xml and install into the controller 72 | String subsystemXml =getSubsystemXml(); 73 | KernelServices services = super.createKernelServicesBuilder(null).setSubsystemXml(subsystemXml).build(); 74 | 75 | //Read the whole model and make sure it looks as expected 76 | ModelNode model = services.readWholeModel(); 77 | Assert.assertTrue(model.get(SUBSYSTEM).hasDefined(SubsystemExtension.SUBSYSTEM_NAME)); 78 | } 79 | 80 | /** 81 | * Starts a controller with a given subsystem xml and then checks that a second 82 | * controller started with the xml marshalled from the first one results in the same model 83 | */ 84 | @Test 85 | public void testParseAndMarshalModel() throws Exception { 86 | //Parse the subsystem xml and install into the first controller 87 | String subsystemXml = getSubsystemXml(); 88 | KernelServices servicesA = super.createKernelServicesBuilder(null).setSubsystemXml(subsystemXml).build(); 89 | //Get the model and the persisted xml from the first controller 90 | ModelNode modelA = servicesA.readWholeModel(); 91 | String marshalled = servicesA.getPersistedSubsystemXml(); 92 | 93 | //Install the persisted xml from the first controller into a second controller 94 | KernelServices servicesB = super.createKernelServicesBuilder(null).setSubsystemXml(marshalled).build(); 95 | ModelNode modelB = servicesB.readWholeModel(); 96 | 97 | //Make sure the models from the two controllers are identical 98 | super.compare(modelA, modelB); 99 | } 100 | 101 | /** 102 | * Tests that the subsystem can be removed 103 | */ 104 | @Test 105 | public void testSubsystemRemoval() throws Exception { 106 | //Parse the subsystem xml and install into the first controller 107 | String subsystemXml = getSubsystemXml(); 108 | KernelServices services = super.createKernelServicesBuilder(null).setSubsystemXml(subsystemXml).build(); 109 | //Checks that the subsystem was removed from the model 110 | super.assertRemoveSubsystemResources(services); 111 | 112 | //TODO Check that any services that were installed were removed here 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/test/resources/org/rhq/wfly/monitor/extension/subsystem.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 13 | 14 | 18 | 19 | 23 | 24 | 25 | 26 | 29 | --------------------------------------------------------------------------------