Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial import

  • Loading branch information...
commit c63822740132da9d4dd8decbf70b547573eedcdf 0 parents
@dougm dougm authored
Showing with 4,339 additions and 0 deletions.
  1. +339 −0 LICENSE
  2. +148 −0 README.markdown
  3. +126 −0 build.xml
  4. +36 −0 etc/javalang-jcollectd.xml
  5. +9 −0 etc/tomcat-jcollectd.xml
  6. +121 −0 src/main/java/org/collectd/mx/CollectdMBean.java
  7. +227 −0 src/main/java/org/collectd/mx/CollectdMBeanRegistry.java
  8. +26 −0 src/main/java/org/collectd/mx/CollectdMBeanRegistryMBean.java
  9. +92 −0 src/main/java/org/collectd/mx/CollectdSummaryMBean.java
  10. +117 −0 src/main/java/org/collectd/mx/MBeanAttribute.java
  11. +246 −0 src/main/java/org/collectd/mx/MBeanCollector.java
  12. +139 −0 src/main/java/org/collectd/mx/MBeanConfig.java
  13. +86 −0 src/main/java/org/collectd/mx/MBeanQuery.java
  14. +148 −0 src/main/java/org/collectd/mx/MBeanReceiver.java
  15. +252 −0 src/main/java/org/collectd/mx/MBeanSender.java
  16. +75 −0 src/main/java/org/collectd/mx/RemoteMBeanSender.java
  17. +97 −0 src/main/java/org/collectd/protocol/DataSource.java
  18. +29 −0 src/main/java/org/collectd/protocol/Dispatcher.java
  19. +100 −0 src/main/java/org/collectd/protocol/Network.java
  20. +70 −0 src/main/java/org/collectd/protocol/Notification.java
  21. +151 −0 src/main/java/org/collectd/protocol/PacketWriter.java
  22. +127 −0 src/main/java/org/collectd/protocol/PluginData.java
  23. +85 −0 src/main/java/org/collectd/protocol/Sender.java
  24. +57 −0 src/main/java/org/collectd/protocol/StdoutDispatcher.java
  25. +161 −0 src/main/java/org/collectd/protocol/TypesDB.java
  26. +286 −0 src/main/java/org/collectd/protocol/UdpReceiver.java
  27. +111 −0 src/main/java/org/collectd/protocol/UdpSender.java
  28. +105 −0 src/main/java/org/collectd/protocol/ValueList.java
  29. +108 −0 src/main/resources/META-INF/types.db
  30. +70 −0 src/test/java/org/collectd/mx/MBeanConfigTest.java
  31. +125 −0 src/test/java/org/collectd/mx/MBeanSenderTest.java
  32. +43 −0 src/test/java/org/collectd/protocol/MulticastReceiverTest.java
  33. +33 −0 src/test/java/org/collectd/protocol/MulticastSenderTest.java
  34. +95 −0 src/test/java/org/collectd/protocol/ReceiverTest.java
  35. +153 −0 src/test/java/org/collectd/protocol/SenderTest.java
  36. +51 −0 src/test/java/org/collectd/protocol/TypesDBTest.java
  37. +95 −0 src/test/java/org/collectd/protocol/ValueListTest.java
339 LICENSE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
148 README.markdown
@@ -0,0 +1,148 @@
+## jcollectd - Java integration for collectd
+
+### collectd
+
+[collectd](http://collectd.org) is a lightweight, extensible system statistics gathering
+daemon written in C for performance and portability. In-process
+plugins can be written in C or Perl. Out-of-process plugins are
+executed on each collection interval or can put values via the
+unixsock plugin.
+
+### jcollectd
+
+The jcollectd package implements the collectd protocol in Java, making
+it possible for Java applications to push data into collectd over the
+wire. A Java app can configure JMX MBean attributes to be collected,
+or use the Java client API directly.
+
+The listener side of the protocol is also supported, including an
+implementation that registers JMX MBeans making it possible to view
+collectd data using a graphical tool such as jconsole.
+
+There is no installation process for jcollectd, as all required files
+are self-contained in *collectd.jar* with no dependecies other than
+Java version 5 or higher. The command-line and java configuration
+options required to use the package are described below.
+
+### MBeanReceiver
+
+The **MBeanReceiver** class listens for collectd packets and publishes the
+data as JMX MBeans. A summary MBean is created to aggregate metrics, where
+the attributes values are the average across all instances.
+The MBeans can be viewed using a tool such as the standard jconsole.
+The MBeanReceiver can be started using the following command:
+
+ java -jar collectd.jar
+
+#### Examples
+
+* Listen on the default IPv4 multicast group **239.192.74.66:25826**:
+
+ java -jar collectd.jar -jconsole
+
+* Listen on the IPv4 unicast address **127.0.0.1:25827** and start
+ jconsole attached locally to the collectd.jar process:
+
+ java -Djcd.laddr=udp://127.0.0.1:25827 -jar collectd.jar -jconsole
+
+* Listen on the default IPv4 multicast group and allow remote JMX
+ connections to RMI/TCP port *25826*:
+
+ java -Dcom.sun.management.jmxremote.port=25826 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -jar collectd.jar
+
+* Connect to the MBeanServer example above from another machine:
+
+ jconsole the-remote-hostname:25826
+
+#### Configuration
+
+* jcd.laddr - UDP listen address, the default is **239.192.74.66:25826**.
+ Example:
+
+ jcd.laddr=udp://localhost:25826
+
+* jcd.ifaddr - The multicast network interface, default is any.
+ Example:
+
+ jcd.ifaddr=eth2
+
+* jcd.mx.summary - Enable summary MBean aggregator, the default is true.
+ Example:
+
+ jcd.mx.summary=false
+
+* jcd.mx.hosts - Filter displayed hosts using a regex, the default is .*.
+ Example:
+
+ jcd.mx.hosts=dev|qa
+
+### MBeanSender
+
+Any Java application can be configured to publish MBean data without
+any code changes. The following example will push java.lang:* MBeans
+to the default collectd multicast group:
+
+ java -Djcd.tmpl=javalang -javaagent:collectd.jar YourMainClass
+
+Tomcat example:
+
+ export CATALINA_OPTS="-Djcd.instance=hudson -Djcd.dest=udp://10.1.0.102 -Djcd.tmpl=javalang,tomcat -javaagent:collectd.jar"
+ ./bin/catalina.sh start
+
+#### Configuration
+
+The jcd.* properties can be defined as System properties or in the
+jcd.properties file:
+
+* jcd.dest - UDP destination(s), the default is
+ **239.192.74.66:25826**. Example:
+
+ jcd.dest=udp://localhost:25826
+
+* jcd.tmpl - jcollectd.xml MBean filter templates (see etc/). Example:
+
+ jcd.tmpl=javalang,tomcat
+
+* jcd.host - The collectd host (Hostname in collectd.conf) defaults to InetAddress.getLocalHost().getHostName(). Example:
+
+ jcd.host=myhost
+
+* jcd.instance - The collectd Plugin Instance, defaults to
+ *java.lang:type=Runtime:Name*. Example:
+
+ jcd.instance=tomcat01
+
+* jcd.beans - ObjectName(s) which are not defined in a filter
+ template. The ObjectName can be a pattern or fully qualified.
+ Multiple ObjectNames are delimited using `#`. All attributes
+ for the matching MBeans will be collected where the attribute value
+ is a *Number*. Example:
+
+ jcd.beans=mydomain:*#foo:type=Stats#bar:type=App,*
+
+* jcd.properties - Path to the jcd.properties file which can be used
+ to define all of the above properties. Example:
+
+ jcd.properties=/path/to/my-jcd.properties
+
+#### XML MBean filters
+
+The MBean filters provide a way to define exactly which MBean
+attributes should be collected, how they should be named in collectd
+and what type the metric is. See the etc/ directory for examples.
+The format is currently subject to change pending feedback and
+documentation will follow.
+
+### See Also
+
+* [collectd](http://collectd.org) - the system statistics collection daemon
+
+* [collectd jmx plugin](http://marc.info/?l=collectd&w=2&r=1&s=jmx&q=b) - Embeds a JVM in collectd
+
+* [jmxetric](http://code.google.com/p/jmxetric/) - JMX injector for Ganglia
+
+### About
+
+Copyright (c) 2009 [Hyperic, Inc.](http://www.hyperic.com/) - See LICENSE
+
+For feedback and discussion, please use collectd's mailinglist: collectd at verplant.org
126 build.xml
@@ -0,0 +1,126 @@
+<project name="jcollectd" default="test" basedir=".">
+ <description>Java collectd</description>
+ <property name="src.main" location="src/main/java" />
+ <property name="src.test" location="src/test/java" />
+ <property name="target" location="target" />
+ <property name="version" value="0.1.0"/>
+ <property name="dist.name" value="jcollectd-${version}"/>
+ <property name="dist" value="${target}/${dist.name}"/>
+
+ <property name="debug" value="true" />
+ <available property="junit" classname="junit.framework.Test"/>
+
+ <path id="alljars">
+ <fileset dir="${target}" includes="lib/collectd.jar"/>
+ </path>
+
+ <target name="init">
+ <mkdir dir="${target}/classes"/>
+ <mkdir dir="${target}/lib"/>
+ </target>
+
+ <target name="compile-tests" depends="init,compile" if="junit">
+ <javac destdir="${target}/classes"
+ debug="${debug}"
+ source="1.5" target="1.5"
+ classpath="${target}/classes">
+ <src path="${src.test}"/>
+ </javac>
+ </target>
+
+ <target name="compile" depends="init">
+ <javac destdir="${target}/classes"
+ debug="${debug}"
+ source="1.5" target="1.5">
+ <src path="${src.main}"/>
+ </javac>
+ </target>
+
+ <target name="jar" depends="compile">
+ <jar jarfile="${target}/lib/collectd.jar">
+ <fileset dir="${target}/classes"
+ excludes="**/*Test.class" />
+ <fileset dir="src/main/resources"/>
+ <fileset dir="." includes="etc/*.xml"/>
+ <manifest>
+ <attribute name="Main-Class"
+ value="org.collectd.mx.MBeanReceiver"/>
+ <attribute name="Premain-Class"
+ value="org.collectd.mx.RemoteMBeanSender"/>
+ </manifest>
+ </jar>
+ </target>
+
+ <target name="test" depends="compile-tests,jar" if="junit">
+ <property name="testresults"
+ location="${target}/testresults"/>
+
+ <mkdir dir="${testresults}"/>
+
+ <junit printsummary="yes" fork="yes"
+ haltonfailure="yes" showoutput="true">
+
+ <classpath>
+ <path refid="alljars"/>
+ <path location="${target}/classes"/>
+ </classpath>
+
+ <formatter type="xml"/>
+
+ <batchtest fork="yes" todir="${testresults}">
+ <fileset dir="${src.test}">
+ <include name="**/*Test.java"/>
+ </fileset>
+ </batchtest>
+ </junit>
+ </target>
+
+ <target name="clean">
+ <delete dir="${target}" />
+ </target>
+
+ <target name="javadoc">
+ <mkdir dir="${target}/javadoc"/>
+ <javadoc packagenames="org.collectd.*"
+ useexternalfile="yes"
+ sourcepath="src/main/java"
+ destdir="${target}/javadoc"
+ author="false"
+ version="false"
+ windowtitle="Java collectd API"
+ doctitle="Jcollectd">
+ <group title="Jcollectd" packages="org.collectd" />
+ <bottom>Copyright &#169; 2009 <![CDATA[<a target="_top" href="http://www.hyperic.com/">Hyperic, Inc.</a>]]>. All Rights Reserved.</bottom>
+ </javadoc>
+ </target>
+
+ <target name="dist" depends="jar,javadoc">
+ <mkdir dir="${dist}"/>
+
+ <copy toDir="${dist}" filtering="on">
+ <fileset dir=".">
+ <include name="build.xml"/>
+ <include name="LICENSE"/>
+ <include name="README*"/>
+ <include name="etc/*.xml"/>
+ <include name="src/**/*.*"/>
+ </fileset>
+ <fileset dir="${target}">
+ <include name="javadoc/**"/>
+ <include name="lib/**"/>
+ </fileset>
+ </copy>
+
+ <tar destfile="${target}/${dist.name}.tar.gz"
+ basedir="${target}"
+ includes="${dist.name}/**"
+ longfile="gnu"
+ compression="gzip"/>
+ </target>
+
+ <target name="markdown">
+ <exec executable="markdown" dir="." output="${target}/README.html">
+ <arg value="README.markdown"/>
+ </exec>
+ </target>
+</project>
36 etc/javalang-jcollectd.xml
@@ -0,0 +1,36 @@
+<jcollectd-config>
+ <mbeans name="java.lang">
+ <mbean name="java.lang:type=Memory" alias="Memory">
+ <attribute name="HeapMemoryUsage.init" alias="Heap_init" units="bytes"/>
+ <attribute name="HeapMemoryUsage.committed" alias="Heap_committed" units="bytes"/>
+ <attribute name="HeapMemoryUsage.used" alias="Heap_used" units="bytes"/>
+ <attribute name="HeapMemoryUsage.max" alias="Heap_max" units="bytes"/>
+ <attribute name="NonHeapMemoryUsage.init" alias="NonHeap_init" units="bytes"/>
+ <attribute name="NonHeapMemoryUsage.committed" alias="NonHeap_committed" units="bytes"/>
+ <attribute name="NonHeapMemoryUsage.used" alias="NonHeap_used" units="bytes"/>
+ <attribute name="NonHeapMemoryUsage.max" alias="NonHeap_max" units="bytes"/>
+ </mbean>
+
+ <mbean name="java.lang:type=Threading" alias="Threading">
+ <attribute name="ThreadCount" alias="Threads"/>
+ <attribute name="DaemonThreadCount" alias="DaemonThreads"/>
+ </mbean>
+
+ <mbean name="java.lang:type=ClassLoading" alias="ClassLoading">
+ <attribute name="LoadedClassCount" alias="LoadedClasses"/>
+ <attribute name="TotalLoadedClassCount" alias="TotLoadedClasses"/>
+ <attribute name="UnloadedClassCount" alias="UnloadedClasses"/>
+ </mbean>
+
+ <!-- ms
+ <mbean name="java.lang:type=Compilation" alias="Compilation">
+ <attribute name="TotalCompilationTime" alias="TotalTime"/>
+ </mbean>
+ -->
+
+ <mbean name="java.lang:type=GarbageCollector,*" alias="GC">
+ <attribute name="CollectionCount" type="counter"/>
+ <attribute name="CollectionTime" type="counter"/>
+ </mbean>
+ </mbeans>
+</jcollectd-config>
9 etc/tomcat-jcollectd.xml
@@ -0,0 +1,9 @@
+<jcollectd-config>
+ <mbeans name="tomcat">
+ <mbean name="Catalina:type=GlobalRequestProcessor,*" alias="GRP">
+ <attribute name="bytesReceived" alias="received" units="bytes" type="counter"/>
+ <attribute name="bytesSent" alias="sent" units="bytes" type="counter"/>
+ <attribute name="errorCount" alias="errors" type="counter"/>
+ </mbean>
+ </mbeans>
+</jcollectd-config>
121 src/main/java/org/collectd/mx/CollectdMBean.java
@@ -0,0 +1,121 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import java.util.Map;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.ReflectionException;
+
+/**
+ * Wrap a Map&lt;String,Number&gt; as a DynamicMBean.
+ */
+public class CollectdMBean implements DynamicMBean {
+
+ private Map<String,Number> _metrics;
+
+ public CollectdMBean(Map<String,Number> metrics) {
+ _metrics = metrics;
+ }
+
+ public Object getAttribute(String key)
+ throws AttributeNotFoundException,
+ MBeanException, ReflectionException {
+
+ Number val = _metrics.get(key);
+ if (val == null){
+ throw new AttributeNotFoundException(key);
+ }
+ return val;
+ }
+
+ public AttributeList getAttributes(String[] attrs) {
+ AttributeList result = new AttributeList();
+ for (int i=0; i<attrs.length; i++) {
+ try {
+ result.add(new Attribute(attrs[i],
+ getAttribute(attrs[i])));
+ } catch (AttributeNotFoundException e) {
+ } catch (MBeanException e) {
+ } catch (ReflectionException e) {
+ }
+ }
+ return result;
+ }
+
+ protected String getAttributeType(String name) {
+ return _metrics.get(name).getClass().getName();
+ }
+
+ protected String getAttributeDescription(String name) {
+ return name + " Attribute";
+ }
+
+ protected MBeanAttributeInfo[] getAttributeInfo() {
+ MBeanAttributeInfo[] attrs =
+ new MBeanAttributeInfo[_metrics.size()];
+ int i=0;
+ for (String name : _metrics.keySet()) {
+ attrs[i++] =
+ new MBeanAttributeInfo(name,
+ getAttributeType(name),
+ getAttributeDescription(name),
+ true, // isReadable
+ false, // isWritable
+ false); // isIs
+ }
+ return attrs;
+ }
+
+ public MBeanInfo getMBeanInfo() {
+ MBeanInfo info =
+ new MBeanInfo(getClass().getName(),
+ CollectdMBean.class.getName(),
+ getAttributeInfo(),
+ null, //constructors
+ null, //operations
+ null); //notifications
+ return info;
+ }
+
+ public Object invoke(String arg0, Object[] arg1, String[] arg2)
+ throws MBeanException, ReflectionException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setAttribute(Attribute arg0)
+ throws AttributeNotFoundException,
+ InvalidAttributeValueException,
+ MBeanException, ReflectionException {
+ // TODO Auto-generated method stub
+ }
+
+ public AttributeList setAttributes(AttributeList arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
227 src/main/java/org/collectd/mx/CollectdMBeanRegistry.java
@@ -0,0 +1,227 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotificationBroadcaster;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+import org.collectd.protocol.DataSource;
+import org.collectd.protocol.Network;
+import org.collectd.protocol.Notification;
+import org.collectd.protocol.Dispatcher;
+import org.collectd.protocol.PluginData;
+import org.collectd.protocol.ValueList;
+
+/**
+ * Convert collectd value_list_t structures to JMX MBeans.
+ * collectd notifications are broadcast as JMX notifications.
+ */
+public class CollectdMBeanRegistry
+ implements Dispatcher, NotificationBroadcaster, CollectdMBeanRegistryMBean {
+
+ public static final String DOMAIN = "collectd";
+
+ private Map<ObjectName,Map<String,Number>> beans =
+ new HashMap<ObjectName,Map<String,Number>>();
+ private NotificationBroadcasterSupport _broadcaster =
+ new NotificationBroadcasterSupport();
+ private static Pattern _hosts = hostPattern();
+
+ private long _notifSequence = 0;
+ private boolean _doSummary =
+ !"false".equals(Network.getProperty("mx.summary"));
+
+ MBeanServer bs =
+ ManagementFactory.getPlatformMBeanServer();
+
+ public void init() throws Exception {
+ ObjectName name = new ObjectName(DOMAIN + ":" + "type=" + "MBeanRegistry");
+ bs.registerMBean(this, name);
+ }
+
+ private static Pattern hostPattern() {
+ String hosts = Network.getProperty("mx.hosts");
+ if (hosts == null) {
+ return null;
+ }
+ return Pattern.compile(hosts);
+ }
+
+ private static boolean excludeHost(PluginData data) {
+ if (_hosts == null) {
+ return false;
+ }
+ return !_hosts.matcher(data.getHost()).find();
+ }
+
+ public void dispatch(Notification notif) {
+ if (excludeHost(notif)) {
+ return;
+ }
+ _broadcaster.sendNotification(new javax.management.
+ Notification(notif.getSeverityString(),
+ notif.getSource(),
+ ++_notifSequence,
+ notif.getTime(),
+ notif.getMessage()));
+ }
+
+ private String getRootName(String host, ValueList vl) {
+ StringBuffer name = new StringBuffer();
+ name.append(DOMAIN).append(':');
+ if (host != null) {
+ name.append("host=").append(host).append(',');
+ }
+ name.append("plugin=").append(vl.getPlugin());
+ if (host == null) {
+ name.append(",*");
+ }
+ return name.toString();
+ }
+
+ Map<String,Number> getMBean(ObjectName name) {
+ return beans.get(name);
+ }
+
+ Number getMBeanAttribute(ObjectName name, String attribute) {
+ Map<String,Number> bean = getMBean(name);
+ if (bean == null) {
+ return null;
+ }
+ return bean.get(attribute);
+ }
+
+ private Map<String,Number> getMBean(ValueList vl) {
+ String instance = vl.getPluginInstance();
+
+ StringBuffer bname = new StringBuffer();
+ bname.append(getRootName(vl.getHost(), vl));
+ if (!vl.defined(instance)) {
+ List<DataSource> ds = vl.getDataSource();
+ if ((ds != null) && (ds.size() > 1)) {
+ //e.g. ds = {rx,tx} -> type=if_octets,typeInstance=en1
+ instance = vl.getTypeInstance();
+ }
+ }
+ if (vl.defined(instance)) {
+ bname.append(',').append("name=").append(instance);
+ }
+
+ ObjectName name;
+ try {
+ name = new ObjectName(bname.toString());
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalArgumentException(bname + ": " + e);
+ }
+
+ Map<String,Number> metrics = getMBean(name);
+ if (metrics != null) {
+ return metrics;
+ }
+
+ metrics = new HashMap<String,Number>();
+ beans.put(name, metrics);
+
+ try {
+ bs.registerMBean(new CollectdMBean(metrics), name);
+
+ if (_doSummary) {
+ ObjectName sname =
+ new ObjectName(getRootName("__summary__", vl));
+ if (!bs.isRegistered(sname)) {
+ ObjectName query = new ObjectName(getRootName(null, vl));
+ CollectdSummaryMBean summary =
+ new CollectdSummaryMBean(query, metrics);
+ summary.setMBeanRegistry(this);
+ bs.registerMBean(summary, sname);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return metrics;
+ }
+
+ public void dispatch(ValueList vl) {
+ if (excludeHost(vl)) {
+ return;
+ }
+ String type = vl.getType();
+ List<Number> values = vl.getValues();
+ int size = values.size();
+ Map<String,Number> metrics = getMBean(vl);
+ String key;
+
+ if (size == 1) {
+ String ti = vl.getTypeInstance();
+ if (vl.defined(ti)) {
+ key = type + "." + ti;
+ }
+ else {
+ key = type;
+ }
+ metrics.put(key, values.get(0));
+ }
+ else {
+ List<DataSource> ds = vl.getDataSource();
+ for (int i=0; i<size; i++) {
+ if (ds != null) {
+ key = type + "." + ds.get(i).getName();
+ }
+ else {
+ key = type + "." + "unknown" + i;
+ }
+ metrics.put(key, values.get(i));
+ }
+ }
+ }
+
+ public void addNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object handback) {
+ _broadcaster.addNotificationListener(listener, filter, handback);
+ }
+
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return new MBeanNotificationInfo[] {
+ new MBeanNotificationInfo(Notification.SEVERITY,
+ javax.management.Notification.class.getName(),
+ "Collectd Notifications"),
+ };
+ }
+
+ public void removeNotificationListener(NotificationListener listener)
+ throws ListenerNotFoundException {
+ _broadcaster.removeNotificationListener(listener);
+ }
+}
26 src/main/java/org/collectd/mx/CollectdMBeanRegistryMBean.java
@@ -0,0 +1,26 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+/**
+ * Interface required to register CollectdMBeanRegistry as an MBean.
+ */
+public interface CollectdMBeanRegistryMBean {
+
+}
92 src/main/java/org/collectd/mx/CollectdSummaryMBean.java
@@ -0,0 +1,92 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.AttributeNotFoundException;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+/**
+ * Aggregate metric values and return the average as the attribute values.
+ */
+public class CollectdSummaryMBean extends CollectdMBean {
+
+ private ObjectName _query;
+ private CollectdMBeanRegistry _registry;
+
+ public CollectdSummaryMBean(ObjectName name,
+ Map<String, Number> metrics) {
+ super(metrics);
+ _query = name;
+ }
+
+ void setMBeanRegistry(CollectdMBeanRegistry registry) {
+ _registry = registry;
+ }
+
+ private Object getAverage(String key) {
+ double sum = 0;
+ double avg;
+ int num = 0;
+ Set<ObjectName> names = _registry.bs.queryNames(_query, null);
+
+ for (ObjectName name : names) {
+ Number val = _registry.getMBeanAttribute(name, key);
+ if (val == null) {
+ continue;
+ }
+ num++;
+ sum += val.doubleValue();
+ }
+
+ if (num == 0) {
+ avg = 0;
+ }
+ else {
+ avg = sum / num;
+ }
+
+ return new Double(avg);
+ }
+
+ public Object getAttribute(String key)
+ throws AttributeNotFoundException,
+ MBeanException,
+ ReflectionException {
+
+ try {
+ return getAverage(key);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ protected String getAttributeType(String name) {
+ return Double.class.getName();
+ }
+
+ protected String getAttributeDescription(String name) {
+ return super.getAttributeDescription(name) + " (summary)";
+ }
+}
117 src/main/java/org/collectd/mx/MBeanAttribute.java
@@ -0,0 +1,117 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import org.collectd.protocol.Network;
+
+/**
+ * MBean attribute to collectd metric metadata mapper.
+ */
+public class MBeanAttribute {
+
+ private String _name;
+ private String _attributeName;
+ private String _compositeKey;
+ private String _typeName;
+ private int _dataType;
+
+ public MBeanAttribute(String attributeName) {
+ this(attributeName, Network.DS_TYPE_GAUGE);
+ }
+
+ public MBeanAttribute(String attributeName, int dataType) {
+ this(attributeName, dataType, null);
+ }
+
+ private static final int getDataType(String typeName) {
+ //XXX types.db mapping
+ if (typeName.equals("counter")) {
+ return Network.DS_TYPE_COUNTER;
+ }
+ else {
+ return Network.DS_TYPE_GAUGE;
+ }
+ }
+
+ public MBeanAttribute(String attributeName, String typeName) {
+ this(attributeName, getDataType(typeName), typeName);
+ }
+
+ public MBeanAttribute(String attributeName, int dataType, String typeName) {
+ _name = attributeName;
+ _dataType = dataType;
+ _typeName = typeName;
+ if (_typeName == null) {
+ if (dataType == Network.DS_TYPE_COUNTER) {
+ _typeName = "counter";
+ }
+ else {
+ _typeName = "gauge";
+ }
+ }
+ int ix = attributeName.indexOf('.');
+ if (ix != -1) {
+ _attributeName = attributeName.substring(0, ix);
+ _compositeKey = attributeName.substring(ix+1);
+ }
+ else {
+ _attributeName = attributeName;
+ }
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public void setName(String name) {
+ _name = name;
+ }
+
+ public String getAttributeName() {
+ return _attributeName;
+ }
+
+ public void setAttributeName(String attributeName) {
+ _attributeName = attributeName;
+ }
+
+ public String getCompositeKey() {
+ return _compositeKey;
+ }
+
+ public void setCompositeKey(String compositeKey) {
+ _compositeKey = compositeKey;
+ }
+
+ public String getTypeName() {
+ return _typeName;
+ }
+
+ public void setTypeName(String typeName) {
+ _typeName = typeName;
+ }
+
+ public int getDataType() {
+ return _dataType;
+ }
+
+ public void setDataType(int dataType) {
+ _dataType = dataType;
+ }
+}
246 src/main/java/org/collectd/mx/MBeanCollector.java
@@ -0,0 +1,246 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+
+import org.collectd.protocol.Network;
+import org.collectd.protocol.ValueList;
+
+/**
+ * Query MBeans and dispatch results upstream.
+ */
+public class MBeanCollector implements Runnable {
+
+ private static final Logger _log =
+ Logger.getLogger(MBeanCollector.class.getName());
+ private MBeanSender _sender;
+ private long _interval = 60;
+ private Map<String,MBeanQuery> _queries =
+ new HashMap<String,MBeanQuery>();
+
+ public MBeanSender getSender() {
+ return _sender;
+ }
+
+ public void setSender(MBeanSender sender) {
+ _sender = sender;
+ }
+
+ public long getInterval() {
+ return _interval;
+ }
+
+ public void setInterval(long interval) {
+ _interval = interval;
+ }
+
+ public Map<String,MBeanQuery> getQueries() {
+ return _queries;
+ }
+
+ public MBeanQuery addMBean(String objectName) {
+ MBeanQuery query = _queries.get(objectName);
+ if (query == null) {
+ try {
+ query = new MBeanQuery(new ObjectName(objectName));
+ } catch (Exception e) {
+ throw new IllegalArgumentException(objectName);
+ }
+ _queries.put(objectName, query);
+ }
+ return query;
+ }
+
+ public MBeanAttribute addMBeanAttribute(String objectName,
+ String attributeName) {
+ MBeanQuery query = addMBean(objectName);
+ if (attributeName != null) {
+ MBeanAttribute attr = new MBeanAttribute(attributeName);
+ query.addAttribute(attr);
+ return attr;
+ }
+ else {
+ return null;
+ }
+ }
+
+ private boolean isNumber(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ return Number.class.isAssignableFrom(obj.getClass());
+ }
+
+ private String getBeanName(ObjectName query, ObjectName name) {
+ Map<String,String> skip;
+ if (query == null) {
+ skip = new HashMap<String,String>();
+ }
+ else {
+ skip = query.getKeyPropertyList();
+ }
+ StringBuffer iname = new StringBuffer();
+ for (Object key : name.getKeyPropertyList().keySet()) {
+ if (skip.get(key) != null) {
+ continue;
+ }
+ if (iname.length() > 0) {
+ iname.append(' ');
+ }
+ iname.append(name.getKeyProperty((String)key));
+ }
+ return iname.toString();
+ }
+
+ private void dispatch(MBeanQuery query, String plugin,
+ String typeInstance,
+ ObjectName name, MBeanAttribute attr,
+ Number val) {
+ if (attr.getDataType() == Network.DS_TYPE_GAUGE) {
+ val = new Double(val.doubleValue());
+ }
+ else {
+ val = new Long(val.longValue());
+ }
+
+ String pluginInstance = query.getPluginInstance();
+ if (pluginInstance == null) {
+ pluginInstance = _sender.getInstanceName();
+ }
+ String beanName = query.getAlias();
+ ValueList vl = new ValueList();
+ vl.setInterval(getInterval());
+ vl.setPlugin(plugin);
+ if (beanName == null){
+ beanName = getBeanName(null, name);
+ }
+ else if (query.getName().isPattern()) {
+ String instName = getBeanName(query.getName(), name);
+ if (instName != null) {
+ beanName += " " + instName;
+ }
+ }
+ vl.setPluginInstance(pluginInstance + "-" + beanName);
+ vl.setType(attr.getTypeName());
+ vl.setTypeInstance(typeInstance);
+ vl.addValue(val);
+ _sender.dispatch(vl);
+ }
+
+ public void collect(MBeanQuery query, ObjectName name) throws Exception {
+ String plugin = query.getPlugin();
+ if (plugin == null) {
+ plugin = name.getDomain();
+ }
+
+ for (MBeanAttribute attr : query.getAttributes()) {
+ String attrName = attr.getAttributeName();
+ Object obj;
+ try {
+ obj = _sender.getMBeanServerConnection().getAttribute(name, attrName);
+ } catch (Exception e) {
+ //XXX remove attr for future collection e.g. UnsupportedOperation
+ continue;
+ }
+ if (obj instanceof CompositeData) {
+ CompositeData data = (CompositeData)obj;
+ String key = attr.getCompositeKey();
+ if (key == null) {
+ //no key specified; collect all
+ Set<String> keys = data.getCompositeType().keySet();
+ for (String ckey : keys) {
+ obj = data.get(ckey);
+ if (!isNumber(obj)) {
+ continue;
+ }
+ dispatch(query, plugin,
+ attrName + "." + ckey,
+ name, attr, (Number)obj);
+ }
+ continue;
+ }
+ else {
+ obj = data.get(key);
+ }
+ }
+ if (!isNumber(obj)) {
+ continue;
+ }
+ dispatch(query, plugin,
+ attr.getName(),
+ name, attr, (Number)obj);
+ }
+ _sender.flush();
+ }
+
+ private void run(MBeanQuery query, ObjectName name) {
+ try {
+ if (query.getAttributes().size() == 0) {
+ query = queryAll(name);
+ }
+ collect(query, name);
+ } catch (Exception e) {
+ //MBean might not be registered yet
+ _log.log(Level.FINE, "collect " + name, e);
+ }
+ }
+
+ private MBeanQuery queryAll(ObjectName name)
+ throws Exception {
+ MBeanQuery query = new MBeanQuery(name);
+ MBeanInfo info = _sender.getMBeanServerConnection().getMBeanInfo(name);
+ MBeanAttributeInfo[] attrs = info.getAttributes();
+ for (int i=0; i<attrs.length; i++) {
+ query.addAttribute(new MBeanAttribute(attrs[i].getName()));
+ }
+ return query;
+ }
+
+ public void run() {
+ for (MBeanQuery query : _queries.values()) {
+ ObjectName name = query.getName();
+ if (name.isPattern()) {
+ Set<ObjectName> beans;
+ try {
+ beans =
+ _sender.getMBeanServerConnection().queryNames(name, null);
+ } catch (Exception e) {
+ _log.warning("queryNames(" + name + "): " + e);
+ return;
+ }
+ for (ObjectName oname : beans) {
+ run(query, oname);
+ }
+ }
+ else {
+ run(query, name);
+ }
+ }
+ }
+}
139 src/main/java/org/collectd/mx/MBeanConfig.java
@@ -0,0 +1,139 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import java.io.File;
+import java.io.InputStream;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * Convert jcollectd.xml filters to MBeanCollect objects.
+ */
+public class MBeanConfig {
+ private XPath _xpath = XPathFactory.newInstance().newXPath();
+
+ private String getAttribute(Node node, String name) {
+ NamedNodeMap attrs = node.getAttributes();
+ if (attrs == null) {
+ return null;
+ }
+ Node item = attrs.getNamedItem(name);
+ if (item == null) {
+ return null;
+ }
+ return item.getNodeValue();
+ }
+
+ private NodeList eval(String name, Node node)
+ throws XPathExpressionException {
+ return (NodeList)_xpath.evaluate(name, node, XPathConstants.NODESET);
+ }
+
+ private NodeList eval(String name, InputSource is)
+ throws XPathExpressionException {
+ return (NodeList)_xpath.evaluate(name, is, XPathConstants.NODESET);
+ }
+
+ public MBeanCollector add(String source) throws Exception {
+ String name = source + "-jcollectd.xml";
+ if (new File(source).exists()) {
+ return add(new InputSource(source));
+ }
+ else if (new File(name).exists()) {
+ return add(new InputSource(name));
+ }
+ else {
+ String[] rs = { name, "etc/" + name, "META-INF/" + name };
+ for (int i=0; i<rs.length; i++) {
+ InputStream is =
+ getClass().getClassLoader().getResourceAsStream(rs[i]);
+ if (is != null) {
+ return add(is);
+ }
+ }
+ return null;
+ }
+ }
+
+ public MBeanCollector add(InputStream is) throws Exception {
+ return add(new InputSource(is));
+ }
+
+ public MBeanCollector add(InputSource is) throws Exception {
+ MBeanCollector collector = new MBeanCollector();
+ final String path = "/jcollectd-config/mbeans";
+ NodeList plugins = eval(path, is);
+
+ int len = plugins.getLength();
+ if (len == 0) {
+ throw new IllegalArgumentException("Missing " + path);
+ }
+
+ for (int i=0; i<len; i++) {
+ Node plugin = plugins.item(i);
+ String pluginName = getAttribute(plugin, "name");
+ NodeList mbeans = eval("mbean", plugin);
+
+ for (int j=0; j<mbeans.getLength(); j++) {
+ Node mbean = mbeans.item(j);
+ String objectName = getAttribute(mbean, "name");
+ String objectNameAlias = getAttribute(mbean, "alias");
+ NodeList attrs = eval("attribute", mbean);
+ MBeanQuery query = collector.addMBean(objectName);
+
+ if (pluginName != null) {
+ query.setPlugin(pluginName);
+ }
+ if (objectNameAlias != null) {
+ query.setAlias(objectNameAlias);
+ }
+
+ for (int k=0; k<attrs.getLength(); k++) {
+ Node attr = attrs.item(k);
+ String attrName = getAttribute(attr, "name");
+ String type = getAttribute(attr, "type");
+ String units = getAttribute(attr, "units");
+ String alias = getAttribute(attr, "alias");
+ if (type == null) {
+ type = "gauge";
+ }
+ MBeanAttribute mattr = new MBeanAttribute(attrName, type);
+ if (alias != null) {
+ mattr.setName(alias);
+ }
+ if (units != null) {
+ //XXX
+ }
+ query.addAttribute(mattr);
+ }
+ }
+ }
+
+ return collector;
+ }
+}
86 src/main/java/org/collectd/mx/MBeanQuery.java
@@ -0,0 +1,86 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.management.ObjectName;
+
+/**
+ * Container for MBeanAttribute objects and
+ * collectd value_list_t structure metadata mapping.
+ */
+public class MBeanQuery {
+ private String _plugin;
+ private String _pluginInstance;
+
+ private ObjectName _name;
+ private String _alias;
+ private Set<MBeanAttribute> _attributes =
+ new HashSet<MBeanAttribute>();
+
+ public MBeanQuery(ObjectName name) {
+ _name = name;
+ }
+
+ public String getPlugin() {
+ return _plugin;
+ }
+
+ public void setPlugin(String plugin) {
+ _plugin = plugin;
+ }
+
+ public String getPluginInstance() {
+ return _pluginInstance;
+ }
+
+ public void setPluginInstance(String pluginInstance) {
+ _pluginInstance = pluginInstance;
+ }
+
+ public ObjectName getName() {
+ return _name;
+ }
+
+ public void setName(ObjectName name) {
+ _name = name;
+ }
+
+ public String getAlias() {
+ return _alias;
+ }
+
+ public void setAlias(String alias) {
+ _alias = alias;
+ }
+
+ public Set<MBeanAttribute> getAttributes() {
+ return _attributes;
+ }
+
+ public void setAttributes(Set<MBeanAttribute> attributes) {
+ _attributes = attributes;
+ }
+
+ public void addAttribute(MBeanAttribute attribute) {
+ _attributes.add(attribute);
+ }
+}
148 src/main/java/org/collectd/mx/MBeanReceiver.java
@@ -0,0 +1,148 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import java.lang.management.ManagementFactory;
+import java.net.DatagramSocket;
+import java.net.MulticastSocket;
+
+import javax.management.MBeanServerFactory;
+
+import org.collectd.protocol.Dispatcher;
+import org.collectd.protocol.UdpReceiver;
+
+/**
+ * Extend UdpReceiver, dispatching collectd data to a
+ * CollectdMBeanRegistry instance. Invoked via Main-Class:
+ * java -jar collectd.jar
+ */
+public class MBeanReceiver
+ extends UdpReceiver
+ implements Runnable {
+
+ private static final String MX = "com.sun.management.jmxremote";
+ private static final String DMX = "-D" + MX;
+
+ public MBeanReceiver() {
+ setDispatcher(new CollectdMBeanRegistry());
+ }
+
+ public MBeanReceiver(Dispatcher dispatcher) {
+ super(dispatcher);
+ }
+
+ private void setup() throws Exception {
+ DatagramSocket socket = getSocket();
+ if (socket instanceof MulticastSocket) {
+ MulticastSocket mcast = (MulticastSocket)socket;
+ System.err.println("Multicast interface=" + mcast.getInterface());
+ }
+ System.err.println(getListenAddress() + ":" +
+ getPort() +
+ " listening...");
+ listen();
+ }
+
+ public void run() {
+ try {
+ setup();
+ } catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ private static String getPid() {
+ String name = ManagementFactory.getRuntimeMXBean().getName();
+ int ix = name.indexOf('@');
+ if (ix == -1) {
+ return null;
+ }
+ return name.substring(0, ix);
+ }
+
+ private static boolean hasMBeanServer() {
+ return MBeanServerFactory.findMBeanServer(null).size() != 0;
+ }
+
+ private static boolean checkMxAgent(String[] args) {
+ if (hasMBeanServer()) {
+ return true;
+ }
+ boolean hasMx = false;
+
+ for (int i=0; i<args.length; i++) {
+ if (args[i].startsWith(DMX)) {
+ hasMx = true;
+ break;
+ }
+ }
+ if (hasMx) {
+ return true;
+ }
+ try {
+ System.err.print("Enabling " + DMX + "...");
+ System.setProperty(MX, "true");
+ //jdk 6 has a better way, but this works w/ 5 + 6
+ sun.management.Agent.startAgent();
+ hasMx = hasMBeanServer();
+ System.err.println(hasMx ? "ok" : "failed");
+ return hasMx;
+ } catch (Throwable t) {
+ System.err.println("failed: " + t);
+ return false;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (!checkMxAgent(args)) {
+ System.err.println("Try using: java " + DMX + " ...");
+ return;
+ }
+ Thread lt = new Thread(new MBeanReceiver());
+ lt.setDaemon(true);
+ lt.start();
+
+ boolean launchJconsole = false;
+ for (int i=0; i<args.length; i++) {
+ String arg = args[i];
+ if (arg.equals("-jconsole")) {
+ launchJconsole = true;
+ }
+ else {
+ System.err.println("Unknown argument: " + arg);
+ return;
+ }
+ }
+ if (launchJconsole) {
+ String pid = getPid();
+ String[] argv = { "jconsole", pid };
+ System.err.println("exec(jconsole, " + pid + ")");
+ try {
+ Process p = Runtime.getRuntime().exec(argv);
+ p.waitFor();
+ System.err.println("jconsole exited");
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ else {
+ lt.join();
+ }
+ }
+}
252 src/main/java/org/collectd/mx/MBeanSender.java
@@ -0,0 +1,252 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import java.io.IOException;
+import java.lang.instrument.Instrumentation;
+import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.collectd.protocol.Network;
+import org.collectd.protocol.Notification;
+import org.collectd.protocol.Dispatcher;
+import org.collectd.protocol.Sender;
+import org.collectd.protocol.UdpSender;
+import org.collectd.protocol.ValueList;
+
+/**
+ * Process -javaagent configuration and schedule MBeanCollector objects.
+ */
+public class MBeanSender implements Dispatcher {
+ private static final Logger _log =
+ Logger.getLogger(MBeanSender.class.getName());
+ private static final String UDP = "udp";
+ private static final String RUNTIME_NAME =
+ "java.lang:type=Runtime";
+
+ private MBeanServerConnection _bs =
+ ManagementFactory.getPlatformMBeanServer();
+
+ private ScheduledExecutorService _scheduler =
+ Executors.newScheduledThreadPool(1, new ThreadFactory() {
+ public Thread newThread(Runnable task) {
+ Thread thread = new Thread(task);
+ thread.setName("jcollectd");
+ thread.setDaemon(true);
+ return thread;
+ }
+ });
+
+ private Map<String,Sender> _senders =
+ new HashMap<String,Sender>();
+
+ private MBeanConfig _config = new MBeanConfig();
+
+ private String _instanceName;
+
+ public void setMBeanServerConnection(MBeanServerConnection server) {
+ _bs = server;
+ }
+
+ public MBeanServerConnection getMBeanServerConnection() {
+ return _bs;
+ }
+
+ private String getRuntimeName() {
+ try {
+ ObjectName name = new ObjectName(RUNTIME_NAME);
+ return (String)getMBeanServerConnection().getAttribute(name, "Name");
+ } catch (Exception e) {
+ return ManagementFactory.getRuntimeMXBean().getName();
+ }
+ }
+
+ public String getInstanceName() {
+ if (_instanceName == null) {
+ _instanceName = Network.getProperty("instance", getRuntimeName());
+ }
+ return _instanceName;
+ }
+
+ public void setInstanceName(String instanceName) {
+ _instanceName = instanceName;
+ }
+
+ public void schedule(MBeanCollector collector) {
+ collector.setSender(this);
+ _scheduler.scheduleAtFixedRate(collector, 0,
+ collector.getInterval(),
+ TimeUnit.SECONDS);
+ }
+
+ public void addSender(String protocol, Sender sender) {
+ _senders.put(protocol, sender);
+ }
+
+ public void addDestination(String url) {
+ final String psep = "://";
+ int ix = url.indexOf(psep);
+ if (ix == -1) {
+ throw new IllegalArgumentException("Malformed url: " + url);
+ }
+ String protocol = url.substring(0, ix);
+ String server = url.substring(ix + psep.length());
+ Sender sender = _senders.get(protocol);
+ if (sender == null) {
+ if (protocol.equals(UDP)) {
+ sender = new UdpSender();
+ addSender(UDP, sender);
+ }
+ else {
+ throw new IllegalArgumentException("Unsupported protocol: " + protocol);
+ }
+ }
+ sender.addServer(server);
+ }
+
+ public MBeanCollector scheduleTemplate(String name) {
+ MBeanCollector collector = null;
+ try {
+ //check for file via path and classpath,
+ //e.g. "javalang", "javalang-jcollectd.xml"
+ collector = _config.add(name);
+ } catch (Exception e) {
+ _log.log(Level.WARNING, "add template " + name +
+ ": " + e.getMessage(), e);
+ }
+ if (collector != null) {
+ schedule(collector);
+ }
+ return collector;
+ }
+
+ public MBeanCollector scheduleMBean(String name) {
+ try {
+ new ObjectName(name);
+ } catch (MalformedObjectNameException e) {
+ _log.log(Level.WARNING, "add MBean " + name +
+ ": " + e.getMessage(), e);
+ return null;
+ }
+ MBeanCollector collector = new MBeanCollector();
+ collector.addMBean(name);
+ schedule(collector);
+ return collector;
+ }
+
+ public MBeanCollector schedule(String name) {
+ MBeanCollector collector = scheduleTemplate(name);
+ if (collector == null) {
+ //assume ObjectName, e.g. "sigar:*"
+ collector = scheduleMBean(name);
+ }
+ return collector;
+ }
+
+ public void dispatch(Notification notification) {
+ for (Sender sender : _senders.values()) {
+ sender.dispatch(notification);
+ }
+ }
+
+ public void dispatch(ValueList values) {
+ for (Sender sender : _senders.values()) {
+ sender.dispatch(values);
+ }
+ }
+
+ public void flush() throws IOException {
+ for (Sender sender : _senders.values()) {
+ sender.flush();
+ }
+ }
+
+ public void shutdown() {
+ _scheduler.shutdownNow();
+ }
+
+ private void addShutdownHook() {
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ public void run() {
+ shutdown();
+ }
+ });
+ }
+
+ public void configure(Properties props) {
+ //java -Djcd.dest=udp://localhost -Djcd.tmpl=javalang -Djcd.beans=sigar:*
+ String dest = props.getProperty("jcd.dest");
+ if (dest != null) {
+ addDestination(dest);
+ }
+ String tmpl = props.getProperty("jcd.tmpl");
+ if (tmpl != null) {
+ for (String t : tmpl.split(",")) {
+ scheduleTemplate(t);
+ }
+ }
+ String beans = props.getProperty("jcd.beans");
+ if (beans != null) {
+ for (String b : beans.split("#")) {
+ scheduleMBean(b);
+ }
+ }
+ }
+
+ protected void init(String args) {
+ if (args == null) {
+ return;
+ }
+ //java -javaagent:collectd.jar="udp://localhost#javalang" -jar sigar.jar
+ String[] argv = args.split("#");
+ for (int i=0; i<argv.length; i++) {
+ String arg = argv[i];
+ if (arg.indexOf("://") != -1) {
+ //e.g. "udp://address:port"
+ addDestination(arg);
+ }
+ else {
+ schedule(arg);
+ }
+ }
+ }
+
+ protected void premainConfigure(String args) {
+ addShutdownHook();
+ configure(System.getProperties());
+ init(args);
+ }
+
+ public static void premain(String args, Instrumentation instr) {
+ MBeanSender sender = new MBeanSender();
+ sender.premainConfigure(args);
+ }
+}
75 src/main/java/org/collectd/mx/RemoteMBeanSender.java
@@ -0,0 +1,75 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.mx;
+
+import java.io.IOException;
+import java.lang.instrument.Instrumentation;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+/**
+ * Out-of-process MBeanSender, polling a remote JMX MBeanServer.
+ */
+public class RemoteMBeanSender extends MBeanSender {
+ private static final Logger _log =
+ Logger.getLogger(RemoteMBeanSender.class.getName());
+
+ public void setMBeanServerConnection(JMXServiceURL url)
+ throws IOException {
+
+ JMXConnector connector =
+ JMXConnectorFactory.connect(url);
+ setMBeanServerConnection(connector.getMBeanServerConnection());
+ }
+
+ public void setMBeanServerConnection(String url)
+ throws IOException {
+
+ if (url.indexOf('/') == -1) {
+ url =
+ "service:jmx:rmi:///jndi/rmi://" +
+ url +
+ "/jmxrmi";
+ }
+
+ _log.fine("URL=" + url);
+ setMBeanServerConnection(new JMXServiceURL(url));
+ }
+
+ public void configure(Properties props) {
+ String url = props.getProperty("jcd.mx.url");
+ if (url != null) {
+ try {
+ setMBeanServerConnection(url);
+ } catch (IOException e) {
+ _log.warning(url + ": " + e);
+ }
+ }
+ super.configure(props);
+ }
+
+ public static void premain(String args, Instrumentation instr) {
+ MBeanSender sender = new RemoteMBeanSender();
+ sender.premainConfigure(args);
+ }
+}
97 src/main/java/org/collectd/protocol/DataSource.java
@@ -0,0 +1,97 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.protocol;
+
+/**
+ * Java representation of collectd/src/plugin.h:data_source_t structure.
+ */
+public class DataSource {
+ public static final int TYPE_COUNTER = 0;
+ public static final int TYPE_GAUGE = 1;
+
+ static final String GAUGE = "GAUGE";
+ static final String COUNTER = "COUNTER";
+ static final String NAN = "U";
+ private static final String[] TYPES = { GAUGE, COUNTER };
+
+ String _name;
+ int _type;
+ double _min;
+ double _max;
+
+ public String getName() {
+ return _name;
+ }
+
+ public void setName(String name) {
+ _name = name;
+ }
+
+ public int getType() {
+ return _type;
+ }
+
+ public void setType(int type) {
+ _type = type;
+ }
+
+ public double getMin() {
+ return _min;
+ }
+
+ public void setMin(double min) {
+ _min = min;
+ }
+
+ public double getMax() {
+ return _max;
+ }
+
+ public void setMax(double max) {
+ _max = max;
+ }
+
+ static double toDouble(String val) {
+ if (val.equals(NAN)) {
+ return Double.NaN;
+ }
+ else {
+ return Double.parseDouble(val);
+ }
+ }
+
+ private String asString(double val) {
+ if (Double.isNaN(val)) {
+ return NAN;
+ }
+ else {
+ return String.valueOf(val);
+ }
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ final char DLM = ':';
+ sb.append(_name).append(DLM);
+ sb.append(TYPES[_type]).append(DLM);
+ sb.append(asString(_min)).append(DLM);
+ sb.append(asString(_max));
+ return sb.toString();
+ }
+}
29 src/main/java/org/collectd/protocol/Dispatcher.java
@@ -0,0 +1,29 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.protocol;
+
+/**
+ * Java interface equivalent of:
+ * collectd/src/plugin.h:plugin_dispatch_values,plugin_dispatch_notification
+ */
+public interface Dispatcher {
+ public void dispatch(ValueList values);
+
+ public void dispatch(Notification notification);
+}
100 src/main/java/org/collectd/protocol/Network.java
@@ -0,0 +1,100 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.collectd.protocol;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+/**
+ * Constants from collectd/src/network.h and jcd.* property configuration.
+ */
+public class Network {
+ public static final int DEFAULT_PORT = 25826;
+ public static final String DEFAULT_V4_ADDR = "239.192.74.66";
+ public static final String DEFAULT_V6_ADDR = "ff18::efc0:4a42";
+
+ public static final int TYPE_HOST = 0x0000;