diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..32e72a6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+target
+*.iml
+.settings
+.classpath
+.project
+*.log
+*.ipr
+*.iws
+*.idea
+.DS_Store
+
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index 96ad45e..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index b26911b..0000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_appdynamics_appd_exts_commons_1_6_4.xml b/.idea/libraries/Maven__com_appdynamics_appd_exts_commons_1_6_4.xml
deleted file mode 100644
index eb58e12..0000000
--- a/.idea/libraries/Maven__com_appdynamics_appd_exts_commons_1_6_4.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_appdynamics_machine_agent_3_7_11.xml b/.idea/libraries/Maven__com_appdynamics_machine_agent_3_7_11.xml
deleted file mode 100644
index 8d819c5..0000000
--- a/.idea/libraries/Maven__com_appdynamics_machine_agent_3_7_11.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_google_guava_guava_11_0_2.xml b/.idea/libraries/Maven__com_google_guava_guava_11_0_2.xml
deleted file mode 100644
index 01a573a..0000000
--- a/.idea/libraries/Maven__com_google_guava_guava_11_0_2.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__commons_io_commons_io_2_4.xml b/.idea/libraries/Maven__commons_io_commons_io_2_4.xml
deleted file mode 100644
index bc2aad0..0000000
--- a/.idea/libraries/Maven__commons_io_commons_io_2_4.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__commons_lang_commons_lang_2_6.xml b/.idea/libraries/Maven__commons_lang_commons_lang_2_6.xml
deleted file mode 100644
index 2ec8376..0000000
--- a/.idea/libraries/Maven__commons_lang_commons_lang_2_6.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__javax_ws_rs_jsr311_api_1_1_1.xml b/.idea/libraries/Maven__javax_ws_rs_jsr311_api_1_1_1.xml
deleted file mode 100644
index a0c4d76..0000000
--- a/.idea/libraries/Maven__javax_ws_rs_jsr311_api_1_1_1.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__junit_junit_4_11.xml b/.idea/libraries/Maven__junit_junit_4_11.xml
deleted file mode 100644
index f33320d..0000000
--- a/.idea/libraries/Maven__junit_junit_4_11.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__log4j_log4j_1_2_17.xml b/.idea/libraries/Maven__log4j_log4j_1_2_17.xml
deleted file mode 100644
index e383c1b..0000000
--- a/.idea/libraries/Maven__log4j_log4j_1_2_17.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_codehaus_jackson_jackson_core_asl_1_9_13.xml b/.idea/libraries/Maven__org_codehaus_jackson_jackson_core_asl_1_9_13.xml
deleted file mode 100644
index 98eb549..0000000
--- a/.idea/libraries/Maven__org_codehaus_jackson_jackson_core_asl_1_9_13.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_codehaus_jackson_jackson_mapper_asl_1_9_13.xml b/.idea/libraries/Maven__org_codehaus_jackson_jackson_mapper_asl_1_9_13.xml
deleted file mode 100644
index 77f3bad..0000000
--- a/.idea/libraries/Maven__org_codehaus_jackson_jackson_mapper_asl_1_9_13.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml
deleted file mode 100644
index f58bbc1..0000000
--- a/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_mockito_mockito_all_1_9_5.xml b/.idea/libraries/Maven__org_mockito_mockito_all_1_9_5.xml
deleted file mode 100644
index 7797878..0000000
--- a/.idea/libraries/Maven__org_mockito_mockito_all_1_9_5.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_nanohttpd_nanohttpd_2_3_0.xml b/.idea/libraries/Maven__org_nanohttpd_nanohttpd_2_3_0.xml
deleted file mode 100644
index 6146614..0000000
--- a/.idea/libraries/Maven__org_nanohttpd_nanohttpd_2_3_0.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_6.xml b/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_6.xml
deleted file mode 100644
index 65280d3..0000000
--- a/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_6.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_slf4j_slf4j_log4j12_1_7_21.xml b/.idea/libraries/Maven__org_slf4j_slf4j_log4j12_1_7_21.xml
deleted file mode 100644
index 5ca45bb..0000000
--- a/.idea/libraries/Maven__org_slf4j_slf4j_log4j12_1_7_21.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_yaml_snakeyaml_1_13.xml b/.idea/libraries/Maven__org_yaml_snakeyaml_1_13.xml
deleted file mode 100644
index 1852ff0..0000000
--- a/.idea/libraries/Maven__org_yaml_snakeyaml_1_13.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index acca38c..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..f5031a2
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,10 @@
+# AppDynamics Kafka Monitoring Extension CHANGELOG
+
+## 2.0.0 - Aug 8, 2018
+1. Moved to 2.0 framework.
+2. Added support for SSL
+3. Added support for composite metrics
+
+
+
+
diff --git a/Kafka_CustomDashboard.png b/Kafka_CustomDashboard.png
deleted file mode 100644
index 4f15a04..0000000
Binary files a/Kafka_CustomDashboard.png and /dev/null differ
diff --git a/LICENSE.txt b/LICENSE.txt
old mode 100644
new mode 100755
index fe4e910..88e8bf8
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,204 +1,13 @@
+Copyright 2018 AppDynamics LLC and its affiliates
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-
- Copyright © 2016 AppDynamics, Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100755
index 0000000..5b424c3
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,4 @@
+Notice and Disclaimer
+
+All Extensions published by AppDynamics are governed by the Apache License v2 and are excluded from the definition of covered software under any agreement between AppDynamics and the User governing AppDynamics Pro Edition, Test & Dev Edition, or any other Editions.
+
diff --git a/Notice.txt b/Notice.txt
deleted file mode 100644
index faf5c89..0000000
--- a/Notice.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-commons-lang
-=============================
-
-Apache Commons Lang
-Copyright 2001-2016 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-
-This product includes software from the Spring Framework,
-under the Apache License 2.0 (see: StringUtils.containsWhitespace())
-
-
-commons-io
-=============================
-
-Apache Commons IO
-Copyright 2002-2016 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-
-
-slf4j-log4j12
-=============================
-
-Copyright (c) 2004-2007 QOS.ch
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-log4j
-=============================
-
-This product includes software developed by
-The Apache Software Foundation (http://www.apache.org/).
-
-This product includes source code based on Sun
-Microsystems' book titled "Java Nativer Interface:
-Programmer's Guide and Specification" and freely available
-to the public at http://java.sun.com/docs/books/jni.
\ No newline at end of file
diff --git a/README.md b/README.md
index 0ba7ac2..f452b47 100755
--- a/README.md
+++ b/README.md
@@ -1,180 +1,218 @@
-AppDynamics Monitoring Extension for use with Kafka
-==============================
-
-An AppDynamics extension to be used with a stand alone Java machine agent to provide metrics for Apache Kafka
-
+Kafka Monitoring Extension for AppDynamics
+===================================================
## Use Case ##
-
-Kafka is a distributed, partitioned, replicated commit log service. It provides the functionality of a messaging system, but with a unique design.
-
+Apache Kafka® is a distributed, fault-tolerant streaming platform. It can be used to process streams of data in
+real-time.The Kafka Monitoring extension can be used with a stand alone machine agent to provide metrics for multiple
+Apache Kafka.
## Prerequisites ##
-
-This extension extracts the metrics from Kafka using the JMX protocol. Make sure you have configured JMX in Kafka
-
-To know more about JMX, please follow the below link
-
- http://docs.oracle.com/javase/6/docs/technotes/guides/management/agent.html
-
-
-## Troubleshooting steps ##
-Before configuring the extension, please make sure to run the below steps to check if the set up is correct.
-
-1. Telnet into your Kafka server from the box where the extension is deployed.
+- In order to use this extension, you do need a [Standalone JAVA Machine Agent](https://docs.appdynamics.com/display/PRO44/Standalone+Machine+Agents).
+or [SIM Agent](https://docs.appdynamics.com/display/PRO44/Server+Visibility).For more details on downloading these products, please visit [Downloads](https://download.appdynamics.com/).
+- The extension also needs a [Kafka](https://kafka.apache.org/quickstart) server installed.
+- The extension needs to be able to connect to Kafka in order to collect and send metrics.
+ To do this, you will have to either establish a remote connection in between the extension and the product,
+ or have an agent on the same machine running the product in order for the extension to collect and send the metrics.
+## Installation ##
+- To build from source, clone this repository and run 'mvn clean install'. This will produce a KafkaMonitor-VERSION.zip in the target directory Alternatively, download the latest release archive from [GitHub](#https://github.com/Appdynamics/kafka-monitoring-extension)
+- Unzip the file KafkaMonitor-\[version\].zip into /monitors/
+- In the newly created directory "KafkaMonitor", edit the config.yml to configure the parameters (See Configuration section below)
+- Restart the Machine Agent
+- In the AppDynamics Metric Browser, look for: In the AppDynamics Metric Browser, look for: Application Infrastructure Performance|\|Custom Metrics|Kafka. If SIM is enabled, look for the Metric Browser for the following metric path under the Servers tab: Application Infrastructure Performance|Root|Custom Metrics|Kafka.
+##### 1. Configuring ports
+- According to [Oracle's explanation](https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8035404), JMX opens 3 different ports:
+ - One is the JMX connector port(the one in config.yml)
+ - One for the RMIRegistry
+ - The third one is an ephemeral port is RMI registry of the local only server
+- We can explicitly configure the first two ports in the Kakfa start-up scripts to avoid it picking random ports.
+- Here port 9999 is used as JMX Connector port 9998 is used as the JMX/RMI port.
+- The third one, however, is an ephemeral port(that's how JMX works).
+- Test connection to the Kafka host and ports 9999 and 9998 from the machine where the extension is installed.
+
+ For example, to test connection to the localhost on port 9999, use
+ nc -v localhost 9999.
+- If the message ```Connection to localhost port 9999 [tcp/distinct] succeeded!```is displayed, it confirms the access to the Kafka server.
+##### 2. Enabling JMX
+ - To enable JMX monitoring for Kafka broker, a JMX_PORT has to be configured to allow monitoring on that port.
+
Edit the Kafka start-up script `/bin/kafka-server-start.sh` to include:
+ `export JMX_PORT=${JMX_PORT:-9999}`
+ This configures port 9999 as the JMX port of Kafka.
+ - Please note that the Kafka server needs to be restarted once the JMX port is added.
+##### 3. Configuring Kafka for non-SSL monitoring
+ This section outlines the configuration of the Kafka start-up scripts if monitoring is not done over SSL.If SSL is being used please skip to [Setting up SSL in Kafka](#sslsettings).
+ - To enable monitoring, some flags need to be set in the Kafka start-up scripts.
+ Edit `/bin/kafka-run-class.sh` and modify `KAFKA_JMX_OPTS` variable like below
+ `KAFKA_JMX_OPTS="-Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.rmi.port=9998 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"`
+ - Also, the changes to `kafka-run-class.sh` has to be made on all the Kafka servers that are being monitored.
+ - Please note that any changes to `kafka-run-class.sh` needs the Kafka server to be restarted for the changes to take effect.
+##### 4. Monitoring over SSL
+ If you need to monitor your Kafka servers securely via SSL, please follow the following steps:
+##### 4.1. Generating SSL Keys
+ - Providing a Keystore and Truststore is mandatory for using SSL. The Keystore is used by the Kafka server, the Truststore is used by the Kafka Monitoring Extension to trust the server.
+ - The extension supports a custom Truststore, and if no Truststore is specified, the extension defaults to the Machine Agent Truststore at `/conf/cacerts.jks`.
+ - You can create your Truststore or choose to use the Machine Agent Truststore at `/conf/cacerts.jks`.
+ - Keytool is a utility that comes with the JDK. Please use the following commands to generate a keystore, and import the certificates into the Truststore.
+ - To use the custom Truststore, please follow steps 1, 2 and 3a listed below.
+ - To to use the Machine Agent Truststore `cacerts.jks`, please follow the steps 1, 2 and 3b listed below to import the certs into `cacerts.jks`.
+
+ #Step #1
+ keytool -keystore kafka.server.keystore.jks -alias localhost -validity 365 -genkey
+
+ #Step #2
+ openssl req -new -x509 -keyout ca-key -out ca-cert -days 365
+
+ #Step #3a: if you are creating your own truststore
+ keytool -keystore kafka.client.truststore.jks -alias CARoot -import -file ca-cert
+
+ #Step #3b: or if you are using Machine Agent truststore
+ keytool -keystore /path/to/MachineAgentHome/conf/cacerts.jks -alias CARoot -import -file ca-cert
+ - Additional info about creating SSL keys is listed [here](https://docs.confluent.io/current/tutorials/security_tutorial.html#creating-ssl-keys-and-certificates).
+##### 4.2. Configuring Kafka for monitoring over SSL ####
+ Edit `/bin/kafka-run-class.sh` and modify `KAFKA_JMX_OPTS` variable, as listed below:
+ ```
+ KAFKA_JMX_OPTS="-Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.rmi.port=9998 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=true -Djavax.net.ssl.keyStore=/Absolute/path/to/keystore -Djavax.net.ssl.keyStorePassword=password -Dcom.sun.management.jmxremote.registry.ssl=false"
+ ```
+##### 4.3. Configuring the Extension to use SSL ####
+ - The extension also needs to be configured to use SSL. In the config.yml of the Kafka Extension, uncomment the `connection` section.
+ ```
+ connection:
+ socketTimeout: 3000
+ connectTimeout: 1000
+ sslProtocol: "TLSv1.2"
+ sslTrustStorePath: "/path/to/truststore/client/kafka.client.truststore.jks" #defaults to conf/cacerts.jks
+ sslTrustStorePassword: "test1234" # defaults to empty
+ sslTrustStoreEncryptedPassword: ""
+ ```
+ - Please note that any changes to the `connection` section of the config.yml, needs the Machine Agent to
+ be restarted for the changes to take effect.
+ - If you need username/password authentication, please set the flag
`-Dcom.sun.management.jmxremote.authenticate=true`
+ in the `KAFKA_JMX_OPTS` variable.Please refer to [Password Settings](#passwordsettings) for further steps.
+##### 5. Password Settings
+If you need password authentication, the password needs to be set in the JVM of the Kafka server.
+To know more on how to set the credentials, please see section `Using Password and Access Files` in [this link](https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html).
+##### 6. Config.yml
+Configure the Kafka monitoring extension by editing the config.yml file in `/monitors/KafkaMonitor/`
+ - Configure the "tier" under which the metrics need to be reported. This can be done by changing the value of `` in
+ `metricPrefix: "Server|Component:|Custom Metrics|Kafka"`.
Please refer this [link](https://community.appdynamics.com/t5/Knowledge-Base/How-to-troubleshoot-missing-custom-metrics-or-extensions-metrics/ta-p/28695) to find Component-ID of your tiers.
+ For example,
+ ```
+ metricPrefix: "Server|Component:19|Custom Metrics|Kafka"
+ ```
+ - Configure the Kafka servers by specifying either `serviceUrl` or `` of all Kafka servers.
+ - Here, `host` is the IP address.
+ of the Kafka server to be monitored, and `port` is the JMX port of the Kafka server.
+ - Please provide `username` & `password` (only if authentication enabled).
+ - `encryptedPassword`(only if password encryption required).
+ - If SSL is being used to securely monitor your Kafka servers, please set `useSsl` as `true`.
+ For example,
+ ```
+ - serviceUrl: "service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi" #provide service URL or the pair
+ host: ""
+ port: ""
+ username: "monitorRole"
+ password: "QED"
+ encryptedPassword: ""
+ displayName: "Local Kafka Server"
+ useSsl: true # set to true if you're using SSL for this server
+ ```
+ - Configure the encyptionKey for encryptionPasswords(only if password encryption required).
+
+ For example,
+ #Encryption key for Encrypted password.
+ encryptionKey: "axcdde43535hdhdgfiniyy576"
+
+ - Configure the connection section only if you are using monitoring over SSL for ANY of Kafka server(s).
+ - Please remove this section if SSL is not required to connect to any of your servers.
+ - If you are using the Machine Agent Truststore, please leave the `sslTrustStorePath` as `""`.
```
- telnet
-
- - It is the jmxremote.port specified.
- - IP address
+ connection:
+ socketTimeout: 3000
+ connectTimeout: 1000
+ sslProtocol: "TLSv1.2"
+ sslTrustStorePath: "/path/to/truststore/client/kafka.client.truststore.jks" #defaults to conf/cacerts.jks
+ sslTrustStorePassword: "test1234" # defaults to empty
+ sslTrustStoreEncryptedPassword: ""
```
-
- If telnet works, it confirm the access to the Kafka server.
-
-
-2. Start jconsole. Jconsole comes as a utility with installed jdk. After giving the correct host and port , check if Kafka
-mbean shows up.
-
-3. It is a good idea to match the mbean configuration in the config.yml against the jconsole. JMX is case sensitive so make
-sure the config matches exact.
-
-## Metrics Provided ##
-
-In addition to the metrics exposed by Kafka, we also add a metric called "Metrics Collected" with a value 0 when an error occurs and 1 when the metrics collection is successful.
-
-Note : By default, a Machine agent or a AppServer agent can send a fixed number of metrics to the controller. To change this limit, please follow the instructions mentioned [here](http://docs.appdynamics.com/display/PRO14S/Metrics+Limits).
-For eg.
-```
- java -Dappdynamics.agent.maxMetrics=2500 -jar machineagent.jar
-```
-
-
-## Installation ##
-
-1. Run "mvn clean install" and find the KafkaMonitor.zip file in the "target" folder. You can also download the KafkaMonitor.zip from [AppDynamics Exchange][].
-2. Unzip as "KafkaMonitor" and copy the "KafkaMonitor" directory to `/monitors`
-
-
-# Configuration ##
-
-Note : Please make sure to not use tab (\t) while editing yaml files. You may want to validate the yaml file using a [yaml validator](http://yamllint.com/)
-
-1. Configure the Kafka instances by editing the config.yml file in `/monitors/KafkaMonitor/`.
-2. Below is the default config.yml which has metrics configured already
- For eg.
-
-```
-### ANY CHANGES TO THIS FILE DOES NOT REQUIRE A RESTART ###
-
-#This will create this metric in all the tiers, under this path
-metricPrefix: Custom Metrics|Kafka
-
-#This will create it in specific Tier/Component. Make sure to replace with the appropriate one from your environment.
-#To find the in your environment, please follow the screenshot https://docs.appdynamics.com/display/PRO42/Build+a+Monitoring+Extension+Using+Java
-#metricPrefix: Server|Component:|Custom Metrics|Kafka
-
-# List of Kafka Instances
-instances:
- - host: "localhost"
- port: 9999
- username:
- password:
- #encryptedPassword:
- #encryptionKey:
- displayName: "Local Kafka Server" #displayName is a REQUIRED field for level metrics.
-
-
-# number of concurrent tasks.
-# This doesn't need to be changed unless many instances are configured
-numberOfThreads: 10
-
-
-# The configuration of different metrics from various mbeans of Kafka server
-# For most cases, the mbean configuration does not need to be changed.
-mbeans:
-
-#All MBeans which have attributes Count and MeanRate
- - mbeanFullPath: ["kafka.server:type=BrokerTopicMetrics,*",
- "kafka.server:type=DelayedFetchMetrics,*",
- "kafka.server:type=KafkaRequestHandlerPool,*",
- "kafka.server:type=ReplicaManager,name=IsrExpandsPerSec",
- "kafka.server:type=ReplicaManager,name=IsrShrinksPerSec",
- "kafka.server:type=SessionExpireListener,*",
- "kafka.network:type=RequestMetrics,*",
- "kafka.controller:type=ControllerStats,*"
- ]
- metrics:
- include:
- - Count: "Count"
- - MeanRate: "MeanRate"
-
-#All MBeans which have attributes Value
- - mbeanFullPath: ["kafka.server:type=DelayedOperationPurgatory,*",
- "kafka.server:type=KafkaServer,name=BrokerState",
- "kafka.server:type=ReplicaFetcherManager,*",
- "kafka.server:type=ReplicaManager,name=LeaderCount",
- "kafka.server:type=ReplicaManager,name=PartitionCount",
- "kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions",
- "kafka.network:type=Processor,*",
- "kafka.network:type=RequestChannel,*",
- "kafka.network:type=SocketServer,*"
- ]
- metrics:
- include:
- - Value: "Value"
-```
-
-3. Configure the path to the config.yml file by editing the in the monitor.xml file in the `/monitors/KafkaMonitor/` directory. Below is the sample
- For Windows, make sure you enter the right path.
-```
-
-
-
- ....
-
-```
-
-## Password Encryption Support
-To avoid setting the clear text password in the config.yaml, please follow the process below to encrypt the password
-
-1. Download the util jar to encrypt the password from [https://github.com/Appdynamics/maven-repo/blob/master/releases/com/appdynamics/appd-exts-commons/1.1.2/appd-exts-commons-1.1.2.jar](https://github.com/Appdynamics/maven-repo/blob/master/releases/com/appdynamics/appd-exts-commons/1.1.2/appd-exts-commons-1.1.2.jar) and navigate to the downloaded directory
-2. Encrypt password from the commandline
-`java -cp appd-exts-commons-1.1.2.jar com.appdynamics.extensions.crypto.Encryptor encryptionKey myPassword`
-3. Specify the passwordEncrypted and encryptionKey in config.yaml
-
-## Custom Dashboard ##
-![](https://github.com/Appdynamics/kafka-monitoring-extension/blob/master/Kafka_CustomDashboard.png?raw=true)
-
-## Enable JMX ##
-To enable JMX Monitoring for Kafka broker, please follow below instructions:
-
-Edit kafka-run-class.sh and modify KAFKA_JMX_OPTS variable like below (please replace <> with your Kafka Broker hostname)
-
-```
-KAFKA_JMX_OPTS="-Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=-Djava.net.preferIPv4Stack=true"
-```
-Add below line in kafka-server-start.sh
-
-```
-export JMX_PORT=${JMX_PORT:-9999}
-```
-
-## Contributing ##
-
-Always feel free to fork and contribute any changes directly via [GitHub][].
-
-## Community ##
-
-Find out more in the [AppDynamics Exchange][].
-
-## Support ##
-
-For any questions or feature request, please contact [AppDynamics Center of Excellence][].
-
-**Version:** 1.0.0
-**Controller Compatibility:** 3.7+
-**Kafka Versions Tested On:** 2.11-0.9.0.0 and 2.11-0.10.1.0
-
-[Github]: https://github.com/Appdynamics/kafka-monitoring-extension
-[AppDynamics Exchange]: https://www.appdynamics.com/community/exchange/kafka-monitoring-extension/
-[AppDynamics Center of Excellence]: mailto:help@appdynamics.com
+ - Configure the numberOfThreads according to the number of Kafka instances that are being monitored on one extension.Each server needs one thread.
+ ``` For example,
+ If number Kafka servers that need to be monitored by one extension is 10, then number of threads is 10
+ numberOfThreads: 10
+ ```
+ - Configure the metrics section.
+ For configuring the metrics, the following properties can be used:
+
+ | Metric Property | Default value | Possible values | Description |
+ | :---------------- | :-------------- | :------------------------------ | :------------------------------------------------------------------------------------------------------------- |
+ | alias | metric name | Any string | The substitute name to be used in the metric browser instead of metric name. |
+ | aggregationType | "AVERAGE" | "AVERAGE", "SUM", "OBSERVATION" | [Aggregation qualifier](https://docs.appdynamics.com/display/PRO44/Build+a+Monitoring+Extension+Using+Java) |
+ | timeRollUpType | "AVERAGE" | "AVERAGE", "SUM", "CURRENT" | [Time roll-up qualifier](https://docs.appdynamics.com/display/PRO44/Build+a+Monitoring+Extension+Using+Java) |
+ | clusterRollUpType | "INDIVIDUAL" | "INDIVIDUAL", "COLLECTIVE" | [Cluster roll-up qualifier](https://docs.appdynamics.com/display/PRO44/Build+a+Monitoring+Extension+Using+Java)|
+ | multiplier | 1 | Any number | Value with which the metric needs to be multiplied. |
+ | convert | null | Any key value map | Set of key value pairs that indicates the value to which the metrics need to be transformed. eg: UP:0, DOWN:1 |
+ | delta | false | true, false | If enabled, gives the delta values of metrics instead of actual values. |
+
+ For example,
+ `objectName: "kafka.server:type=BrokerTopicMetrics, * ` will fetch metrics of all objects nested under `BrokerTopicMetrics`.
+
+ - objectName: "kafka.server:type=BrokerTopicMetrics,*"
+ metrics:
+ - Count:
+ alias: "Count"
+ multiplier: ""
+ delta: false
+ aggregationType: "OBSERVATION"
+ timeRollUpType: "AVERAGE"
+ clusterRollUpType: "INDIVIDUAL"
+
+ - MeanRate:
+ alias: "Mean Rate"
+ multiplier: ""
+ delta: false
+ aggregationType: "AVERAGE"
+ timeRollUpType: "AVERAGE"
+ clusterRollUpType: "INDIVIDUAL"
+ **All these metric properties are optional, and the default value shown in the table is applied to the metric(if a property has not been specified) by default.** If you need a metric from a specific object under an mBean, `objectName: kafka.server:type=ReplicaManager,name=IsrExpandsPerSec` will return only those metrics corresponding to the `IsrExpandsPerSec` object.
+##### 7. Validating config.yml:
+- Please copy all the contents of the config.yml file and go to [YamlLint](http://www.yamllint.com/).
+- On reaching the website, paste the contents and press the “Go” button on the bottom left.
+- If you get a valid output, that means your formatting is correct and you may move on to the next step.
+##### 8. Metrics
+- This extension collects metrics via JMX and can be configured to report any of the metrics that Kafka exposes. It provides metrics on Kafka server, controller and the network.
+- In addition, it also provides the JVM metrics:
+`HeapMemoryUsage.committed, HeapMemoryUsage.max, NonHeapMemoryUsage.committed, NonHeapMemoryUsage.max`
+- There is also a `HeartBeat` metric under`kafka.server` which denotes whether the connection from the extension to the Kafka server was successful(1 = Successful, 0 = Unsuccessful).
+- By default, a Machine agent or a AppServer agent can send a fixed number of metrics to the controller.
+ To change this limit, please follow the instructions mentioned [here](http://docs.appdynamics.com/display/PRO14S/Metrics+Limits).
+## Credentials Encryption
+Please visit [this](https://community.appdynamics.com/t5/Knowledge-Base/How-to-use-Password-Encryption-with-Extensions/ta-p/29397) page to get detailed instructions on password encryption. The steps in this document will guide you through the whole process.
+## Extensions Workbench
+Workbench is an inbuilt feature provided with each extension in order to assist you to fine tune the extension setup before you actually deploy it on the controller. Please review the following
+[document](https://community.appdynamics.com/t5/Knowledge-Base/How-to-use-the-Extensions-WorkBench/ta-p/30130) for how to use the Extensions WorkBench
+## Troubleshooting
+Please follow the steps listed in the [extensions troubleshooting document](https://community.appdynamics.com/t5/Knowledge-Base/How-to-troubleshoot-missing-custom-metrics-or-extensions-metrics/ta-p/28695) in order to troubleshoot your issue.
+These are a set of common issues that customers might have faced during the installation of the extension. If these don't solve your issue, please follow the last step on the troubleshooting-document to contact the support team.
+## Support Tickets
+If after going through the Troubleshooting Document you have not been able to get your extension working, please file a ticket and add the following information.
+Please provide the following in order for us to assist you better.
+1. Stop the running machine agent
.
+2. Delete all existing logs under /logs
.
+3. Please enable debug logging by editing the file /conf/logging/log4j.xml. Change the level value of the following elements to debug.
+ ```
+
+
+ ```
+4. Start the machine agent and please let it run for 10 mins. Then zip and upload all the logs in the directory /logs/*.
+5. Attach the zipped /conf/* directory here.
+6. Attach the zipped /monitors/ directory here
.
+For any support related questions, you can also contact help@appdynamics.com.
+## Contributing
+Always feel free to fork and contribute any changes directly via [GitHub](https://github.com/Appdynamics/kafka-monitoring-extension).
+## Version
+| Name | Version |
+| :---------------------------| :---------------------------|
+| Extension Version: | 2.0.0 |
+| Controller Compatibility: | 4.0 or Later |
+| Tested On: | Apache Kafka 2.11 |
+| Operating System Tested On: | Mac OS |
+| Last updated On: | Aug 27, 2018 |
+| List of changes to this extension| [Change log](https://github.com/Appdynamics/kafka-monitoring-extension/blob/master/Changelog.md)
diff --git a/kafka-monitoring-extension.iml b/kafka-monitoring-extension.iml
deleted file mode 100644
index c13495a..0000000
--- a/kafka-monitoring-extension.iml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index e85060b..81a1d95 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,19 +4,21 @@
com.appdynamics.extensions
kafka-monitoring-extension
- 1.0.3
+ 2.0.0
jar
kafka-monitoring-extension
http://maven.apache.org
+
UTF-8
yyyy-MM-dd HH:mm:ss
+ ${project.build.directory}/KafkaMonitor
com.appdynamics
appd-exts-commons
- 1.6.4
+ 2.1.0
commons-lang
@@ -59,6 +61,24 @@
4.11
test
+
+ org.mockito
+ mockito-all
+ 1.9.5
+ test
+
+
+ org.mockito
+ mockito-all
+ 1.9.5
+ test
+
+
+ org.mockito
+ mockito-all
+ 1.9.5
+ test
+
${project.artifactId}
@@ -68,8 +88,8 @@
maven-compiler-plugin
2.3.2
-
- 1.5
+
+ 1.8
@@ -119,11 +139,12 @@
install
-
+
-
-
+
+
+
@@ -132,7 +153,7 @@
-
+
@@ -175,4 +196,4 @@
scm:git:https://github.com/Appdynamics/kafka-monitoring-extension.git
-
+
\ No newline at end of file
diff --git a/src/main/java/com/appdynamics/extensions/kafka/ConfigConstants.java b/src/main/java/com/appdynamics/extensions/kafka/ConfigConstants.java
deleted file mode 100644
index 0a11bce..0000000
--- a/src/main/java/com/appdynamics/extensions/kafka/ConfigConstants.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2018. AppDynamics LLC and its affiliates.
- * All Rights Reserved.
- * This is unpublished proprietary source code of AppDynamics LLC and its affiliates.
- * The copyright notice above does not evidence any actual or intended publication of such source code.
- *
- */
-
-package com.appdynamics.extensions.kafka;
-
-
-public class ConfigConstants {
-
-
- public static final String INCLUDE = "include";
-
- public static final String EXCLUDE = "exclude";
-
- static final String MULTIPLIER = "multiplier";
-
- static final String METRIC_TYPE = "metricType";
-
- static final String AGGREGATION = "aggregation";
-
- static final String CONVERT = "convert";
-
- static final String INSTANCES = "instances";
-
- static final String SERVICE_URL = "serviceUrl";
-
- static final String HOST = "host";
-
- static final String PORT = "port";
-
- static final String USERNAME = "username";
-
- static final String PASSWORD = "password";
-
- static final String ENCRYPTION_KEY = "encryptionKey";
-
- static final String ENCRYPTED_PASSWORD = "encryptedPassword";
-
- static final String DISPLAY_NAME = "displayName";
-
- static final String MBEANS = "mbeans";
-
- public static final String OBJECT_NAME = "objectName";
-
- public static final String METRICS = "metrics";
-
-
-
-}
diff --git a/src/main/java/com/appdynamics/extensions/kafka/JMXConnectionAdapter.java b/src/main/java/com/appdynamics/extensions/kafka/JMXConnectionAdapter.java
index 8cfbbdf..3602aa6 100644
--- a/src/main/java/com/appdynamics/extensions/kafka/JMXConnectionAdapter.java
+++ b/src/main/java/com/appdynamics/extensions/kafka/JMXConnectionAdapter.java
@@ -1,29 +1,30 @@
-/*
- * Copyright 2018. AppDynamics LLC and its affiliates.
- * All Rights Reserved.
- * This is unpublished proprietary source code of AppDynamics LLC and its affiliates.
- * The copyright notice above does not evidence any actual or intended publication of such source code.
+/**
+ * Copyright 2018 AppDynamics, Inc.
*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package com.appdynamics.extensions.kafka;
-
+import com.appdynamics.extensions.kafka.utils.Constants;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
-import javax.management.Attribute;
-import javax.management.AttributeList;
-import javax.management.InstanceNotFoundException;
-import javax.management.IntrospectionException;
-import javax.management.MBeanAttributeInfo;
-import javax.management.MBeanServerConnection;
-import javax.management.ObjectInstance;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
+import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
@@ -37,39 +38,33 @@ public class JMXConnectionAdapter {
private final String username;
private final String password;
- private JMXConnectionAdapter(String host, int port, String username, String password) throws MalformedURLException {
- this.serviceUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi");
- this.username = username;
- this.password = password;
+ private JMXConnectionAdapter(Map requestMap) throws MalformedURLException {
+ if(!Strings.isNullOrEmpty(requestMap.get(Constants.SERVICE_URL)))
+ this.serviceUrl = new JMXServiceURL(requestMap.get(Constants.SERVICE_URL));
+ else
+ { this.serviceUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" +
+ requestMap.get(Constants.HOST) + ":" + requestMap.get(Constants.PORT) + "/jmxrmi");}
+ this.username = requestMap.get(Constants.USERNAME);
+ this.password = requestMap.get(Constants.PASSWORD);
}
- private JMXConnectionAdapter(String serviceUrl, String username, String password) throws MalformedURLException {
- this.serviceUrl = new JMXServiceURL(serviceUrl);
- this.username = username;
- this.password = password;
+ static JMXConnectionAdapter create( Map requestMap) throws MalformedURLException {
+ return new JMXConnectionAdapter(requestMap);
}
+ JMXConnector open(Map connectionMap) throws IOException {
+ JMXConnector jmxConnector;
+ final Map env = new HashMap<>();
- static JMXConnectionAdapter create(String serviceUrl, String host, int port, String username, String password) throws MalformedURLException {
- if (Strings.isNullOrEmpty(serviceUrl)) {
- return new JMXConnectionAdapter(host, port, username, password);
- } else {
- return new JMXConnectionAdapter(serviceUrl, username, password);
+ if(Boolean.valueOf(connectionMap.get(Constants.USE_SSL).toString())) {
+ SslRMIClientSocketFactory sslRMIClientSocketFactory = new SslRMIClientSocketFactory();
+ env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, sslRMIClientSocketFactory);
}
- }
- JMXConnector open() throws IOException {
- JMXConnector jmxConnector;
- final Map env = new HashMap();
- if (!Strings.isNullOrEmpty(username)) {
- env.put(JMXConnector.CREDENTIALS, new String[]{username, password});
- jmxConnector = JMXConnectorFactory.connect(serviceUrl, env);
- } else {
- jmxConnector = JMXConnectorFactory.connect(serviceUrl);
- }
- if (jmxConnector == null) {
- throw new IOException("Unable to connect to Mbean server");
- }
+ if (!Strings.isNullOrEmpty(this.username)) {env.put(JMXConnector.CREDENTIALS, new String[]{username, password});}
+ jmxConnector = JMXConnectorFactory.connect(this.serviceUrl,env);
+ if (jmxConnector == null) { throw new IOException("Unable to connect to Mbean server"); }
+ jmxConnector = JMXConnectorFactory.connect(this.serviceUrl,env);
return jmxConnector;
}
@@ -79,24 +74,28 @@ void close(JMXConnector jmxConnector) throws IOException {
}
}
- public Set queryMBeans(JMXConnector jmxConnection, ObjectName objectName) throws IOException {
+ public Set queryMBeans( JMXConnector jmxConnection, ObjectName objectName)
+ throws IOException {
MBeanServerConnection connection = jmxConnection.getMBeanServerConnection();
return connection.queryMBeans(objectName, null);
}
- public List getReadableAttributeNames(JMXConnector jmxConnection, ObjectInstance instance) throws IntrospectionException, ReflectionException, InstanceNotFoundException, IOException {
+ public List getReadableAttributeNames( JMXConnector jmxConnection, ObjectInstance instance)
+ throws IntrospectionException, ReflectionException, InstanceNotFoundException, IOException {
MBeanServerConnection connection = jmxConnection.getMBeanServerConnection();
- List attrNames = Lists.newArrayList();
+ List attributeNames = Lists.newArrayList();
MBeanAttributeInfo[] attributes = connection.getMBeanInfo(instance.getObjectName()).getAttributes();
- for (MBeanAttributeInfo attr : attributes) {
- if (attr.isReadable()) {
- attrNames.add(attr.getName());
+ for (MBeanAttributeInfo attribute : attributes) {
+ if (attribute.isReadable()) {
+ attributeNames.add(attribute.getName());
}
}
- return attrNames;
+ return attributeNames;
}
- public List getAttributes(JMXConnector jmxConnection, ObjectName objectName, String[] strings) throws IOException, ReflectionException, InstanceNotFoundException {
+ public List getAttributes( JMXConnector jmxConnection, ObjectName objectName,
+ String[] strings) throws IOException, ReflectionException,
+ InstanceNotFoundException {
MBeanServerConnection connection = jmxConnection.getMBeanServerConnection();
AttributeList list = connection.getAttributes(objectName, strings);
if (list != null) {
@@ -104,9 +103,4 @@ public List getAttributes(JMXConnector jmxConnection, ObjectName obje
}
return Lists.newArrayList();
}
-
-
- boolean matchAttributeName(Attribute attribute, String matchedWith) {
- return attribute.getName().equalsIgnoreCase(matchedWith);
- }
}
diff --git a/src/main/java/com/appdynamics/extensions/kafka/KafkaMonitor.java b/src/main/java/com/appdynamics/extensions/kafka/KafkaMonitor.java
index 7904eff..5637b08 100644
--- a/src/main/java/com/appdynamics/extensions/kafka/KafkaMonitor.java
+++ b/src/main/java/com/appdynamics/extensions/kafka/KafkaMonitor.java
@@ -8,175 +8,52 @@
package com.appdynamics.extensions.kafka;
-import static com.appdynamics.TaskInputArgs.PASSWORD_ENCRYPTED;
-import static com.appdynamics.extensions.kafka.ConfigConstants.DISPLAY_NAME;
-import static com.appdynamics.extensions.kafka.ConfigConstants.ENCRYPTED_PASSWORD;
-import static com.appdynamics.extensions.kafka.ConfigConstants.HOST;
-import static com.appdynamics.extensions.kafka.ConfigConstants.INSTANCES;
-import static com.appdynamics.extensions.kafka.ConfigConstants.MBEANS;
-import static com.appdynamics.extensions.kafka.ConfigConstants.PASSWORD;
-import static com.appdynamics.extensions.kafka.ConfigConstants.PORT;
-import static com.appdynamics.extensions.kafka.ConfigConstants.SERVICE_URL;
-import static com.appdynamics.extensions.kafka.ConfigConstants.USERNAME;
-import static com.appdynamics.extensions.kafka.Util.convertToString;
-import com.appdynamics.TaskInputArgs;
-import com.appdynamics.extensions.conf.MonitorConfiguration;
-import com.appdynamics.extensions.crypto.CryptoUtil;
-import com.appdynamics.extensions.util.MetricWriteHelper;
-import com.appdynamics.extensions.util.MetricWriteHelperFactory;
-import com.google.common.base.Strings;
-import com.google.common.collect.Maps;
-import com.singularity.ee.agent.systemagent.api.AManagedMonitor;
-import com.singularity.ee.agent.systemagent.api.TaskExecutionContext;
-import com.singularity.ee.agent.systemagent.api.TaskOutput;
-import com.singularity.ee.agent.systemagent.api.exception.TaskExecutionException;
-import org.apache.log4j.ConsoleAppender;
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-import org.apache.log4j.PatternLayout;
+import com.appdynamics.extensions.ABaseMonitor;
+import com.appdynamics.extensions.TasksExecutionServiceProvider;
+import com.appdynamics.extensions.kafka.utils.Constants;
+import com.appdynamics.extensions.kafka.utils.SslUtils;
+import com.appdynamics.extensions.util.AssertUtils;
+import org.slf4j.LoggerFactory;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.HashMap;
+import java.io.File;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-public class KafkaMonitor extends AManagedMonitor {
- private static final Logger logger = Logger.getLogger(KafkaMonitor.class);
- private static final String CONFIG_ARG = "config-file";
- private static final String METRIC_PREFIX = "Custom Metrics|Kafka|";
+import static com.appdynamics.extensions.kafka.utils.Constants.DEFAULT_METRIC_PREFIX;
-
- private boolean initialized;
- private MonitorConfiguration configuration;
-
- public KafkaMonitor() {
- System.out.println(logVersion());
+public class KafkaMonitor extends ABaseMonitor {
+ private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KafkaMonitor.class);
+ @Override
+ protected void onConfigReload(File file) {
+ Map configMap = this.getContextConfiguration().getConfigYml();
+ SslUtils sslUtils = new SslUtils();
+ sslUtils.setSslProperties(configMap);
}
- public TaskOutput execute(Map taskArgs, TaskExecutionContext out) throws TaskExecutionException {
- logVersion();
- if (!initialized) {
- initialize(taskArgs);
- }
- logger.debug(String.format("The raw arguments are {}", taskArgs));
- configuration.executeTask();
- logger.info("Kafka monitor run completed successfully.");
- return new TaskOutput("Kafka monitor run completed successfully.");
-
- }
+ protected String getDefaultMetricPrefix() { return DEFAULT_METRIC_PREFIX; }
- private void initialize(Map taskArgs) {
- if (!initialized) {
- //read the config.
- final String configFilePath = taskArgs.get(CONFIG_ARG);
- MetricWriteHelper metricWriteHelper = MetricWriteHelperFactory.create(this);
- MonitorConfiguration conf = new MonitorConfiguration(METRIC_PREFIX, new TaskRunnable(), metricWriteHelper);
- conf.setConfigYml(configFilePath);
- conf.checkIfInitialized(MonitorConfiguration.ConfItem.CONFIG_YML, MonitorConfiguration.ConfItem.EXECUTOR_SERVICE,
- MonitorConfiguration.ConfItem.METRIC_PREFIX, MonitorConfiguration.ConfItem.METRIC_WRITE_HELPER);
- this.configuration = conf;
- initialized = true;
- }
+ public String getMonitorName() {
+ return Constants.KAFKA_MONITOR;
}
- private class TaskRunnable implements Runnable {
-
- public void run() {
- Map config = configuration.getConfigYml();
- if (config != null) {
- List