Permalink
Browse files

Add org.munin.plugin.jmx.Beans (class to fetch any bean via jmx), and…

… node.d/jmx_tomcat_dbpools.in (an example plugin that makes use of it).
  • Loading branch information...
1 parent 50989cd commit 32c46a34f9858128a6f3d7e753f2f49a63a7cdeb @jomono jomono committed Dec 6, 2010
Showing with 258 additions and 0 deletions.
  1. +108 −0 plugins/javalib/org/munin/plugin/jmx/Beans.java
  2. +150 −0 plugins/node.d/jmx_tomcat_dbpools.in
@@ -0,0 +1,108 @@
+package org.munin.plugin.jmx;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.MalformedURLException;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.MalformedObjectNameException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import java.util.Set;
+import javax.management.JMException;
+import java.lang.management.ManagementFactory;
+
+import org.munin.plugin.jmx.Config;
+
+public class Beans {
+
+ protected ObjectName name;
+ protected Set<ObjectName> mbeans;
+ protected Config config;
+ protected MBeanServerConnection connection;
+ protected String[] filter;
+
+ public Beans(String args[]) {
+ config = getConfig(args);
+ filter = new String[args.length - 1];
+ this.populateBeanList(args[0]);
+ for(int i=1; i<args.length; i++) {
+ filter[i-1]=args[i];
+ }
+ java.util.Arrays.sort(filter);
+ }
+
+ protected MBeanServerConnection getConnection() {
+ if (connection == null) {
+ try {
+ connection = BasicMBeanConnection.get(config);
+ } catch (MalformedURLException e) {
+ throw new IllegalStateException(
+ "Failed to get MBean Server Connection", e);
+ } catch (IOException e) {
+ throw new IllegalStateException(
+ "Failed to get MBean Server Connection", e);
+ }
+ }
+ return connection;
+ }
+
+ protected void populateBeanList(String strName) {
+ try {
+ name = new ObjectName(strName);
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalStateException("Failed to get provider class", e);
+ }
+
+ try {
+ mbeans = getConnection().queryNames(name,null);
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to get provider class", e);
+ }
+ }
+
+ protected void printBeans() {
+ for (ObjectName bean : mbeans) {
+ MBeanInfo info;
+ try {
+ info = connection.getMBeanInfo(bean);
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to get provider class", e);
+ }
+ MBeanAttributeInfo[] attributes = info.getAttributes();
+ for (MBeanAttributeInfo attr : attributes) {
+ if (filter.length == 0 || java.util.Arrays.binarySearch(filter, attr.getName()) >= 0) {
+ Object val;
+ try {
+ val = connection.getAttribute(bean,attr.getName());
+ } catch (Exception e) {
+ val = e;
+ }
+
+ System.out.println(bean + "\t" + attr.getName() + "\t" + val);
+ }
+ }
+ }
+ }
+
+ private static Config getConfig(String[] args) {
+ String prefix;
+ if (args.length >= 2) {
+ prefix = args[1];
+ } else {
+ prefix = null;
+ }
+ return new Config(prefix);
+ }
+
+
+ public static void main(String args[]) {
+ Beans bs = new Beans(args);
+ bs.printBeans();
+ }
+}
+
+
+
+// vim: ts=4:et:ai
@@ -0,0 +1,150 @@
+#!@@PERL@@ -w
+# -*- perl -*-
+
+=head1 NAME
+
+jmx_ - Wildcard plugin to monitor Java application servers via JMX
+
+=head1 APPLICABLE SYSTEMS
+
+Tested with Tomcat 4.1/5.0/5.5/6.0 on Sun JVM 5/6 and OpenJDK.
+
+Any JVM that supports JMX should in theory do.
+
+Needs nc in path for autoconf.
+
+=head1 CONFIGURATION
+
+ [jmx_*]
+ env.ip 127.0.0.1
+ env.port 5400
+ env.category jvm
+ env.username monitorRole
+ env.password SomethingSecret
+ # The critical and warning levels are in % of the pool size
+ env.critical 90
+ env.warning 70
+
+ env.JRE_HOME /usr/lib/jvm/java-6-sun/jre
+
+Needed configuration on the Tomcat side: add
+
+ -Dcom.sun.management.jmxremote \
+ -Dcom.sun.management.jmxremote.port=5400 \
+ -Dcom.sun.management.jmxremote.ssl=false \
+ -Dcom.sun.management.jmxremote.authenticate=false
+
+to CATALINA_OPTS in your startup scripts.
+
+Replace authenticate=false with
+ -Dcom.sun.management.jmxremote.password.file=/etc/tomcat/jmxremote.password \
+ -Dcom.sun.management.jmxremote.access.file=/etc/tomcat/jmxremote.access
+ ...if you want authentication.
+
+jmxremote.password:
+ monitorRole SomethingSecret
+
+jmxremote.access:
+ monitorRole readonly
+
+You may need higher access levels for some counters, notably ThreadsDeadlocked.
+
+=head1 BUGS
+
+No encryption supported in the JMX connection.
+
+The plugins available reflect the most interesting aspects of a
+JVM runtime. This should be extended to cover things specific to
+Tomcat, JBoss, Glassfish and so on. Patches welcome.
+
+=head1 AUTHORS
+
+=encoding UTF-8
+
+Code written by Jimmy Olsen, Redpill Linpro AS. This code also
+uses code written by Mo Amini, Diyar Amin and Younes Hajji,
+Høgskolen i Oslo/Oslo University College.
+
+Previous work on JMX plugin by Aleksey Studnev. Support for
+authentication added by Ingvar Hagelund, Redpill Linpro AS.
+
+=head1 LICENSE
+
+GPLv2
+
+=head1 MAGIC MARKERS
+
+ #%# family=manual
+
+=cut
+
+use strict;
+
+my $beans="Catalina:type=DataSource,class=javax.sql.DataSource,name=*";
+my $munin_jar='@@JAVALIBDIR@@/munin-jmx-plugins.jar';
+my $java='@@JAVARUN@@';
+my $ip=$ENV{'ip'} || "127.0.0.";
+my $port=$ENV{'port'} || "5400";
+
+if($ENV{'JRE_HOME'}) {
+ $java="$ENV{'JRE_HOME'}/bin/java";
+}
+
+sub config() {
+ open(CMD, "-|", $java, "-cp", $munin_jar, "org.munin.plugin.jmx.Beans", $beans, "maxActive") or die "Error: could not run \"$java -cp $munin_jar org.munin.plugin.jmx.Beans maxActive\": $!";
+
+ print "graph_title Tomcat database pool overview\n";
+ print "graph_vlabel current connections\n";
+ print "graph_info Shows the number of connections used for every pool in a Tomcat instance\n";
+ print "graph_category tomcat\n";
+
+ while(my $line = <CMD>) {
+ chomp($line);
+ if($line =~ /^[^\t]+,name="([^\t"]+)"\t([^\t]+)\t([^\t]+)$/) {
+ my $max = $3;
+ my $label = $1;
+ my $field = "v" . $label; # Prefix with a known good char, as field names can't start with a number
+ $field =~ s/[^A-Za-z0-9]/_/g;
+ print "$field.label $label\n$field.max $max\n";
+ if(defined $ENV{'critical'}) {
+ print "$field.critical " . ($max * $ENV{'critical'} / 100), "\n";
+ }
+ if(defined $ENV{'warning'}) {
+ print "$field.warning " . ($max * $ENV{'warning'} / 100), "\n";
+ }
+ }
+ }
+ close(CMD);
+}
+
+sub fetch() {
+
+ # Fetch bean values (through jmx) via the command line. We basically run the class "org.munin.plugin.jmx.Beans"
+ # with the parameters <bean> and <filter>, the <bean> being a bean pattern to fetch (in this case
+ # "Catalina:type=DataSource,class=javax.sql.DataSource,name=*", and <filter> being "numActive" (the single field
+ # we're actually interested in). We can fetch multiple fields by listing them all as parameters, or list all fields
+ # by not supplying a filter (only a bean).
+ open(CMD, "-|", $java, "-cp", $munin_jar, "org.munin.plugin.jmx.Beans", $beans, "numActive") or die "Error: could not run \"$java -cp $munin_jar org.munin.plugin.jmx.Beans maxActive\": $!";
+
+ while(my $line = <CMD>) {
+ chomp($line);
+ if($line =~ /^[^\t]+,name="([^\t"]+)"\t([^\t]+)\t([^\t]+)$/) {
+ my $num = $3;
+ my $field = "v" . $1; # Prefix with a known good char, as field names can't start with a number
+ $field =~ s/[^A-Za-z0-9]/_/g;
+ print "$field.value $num\n";
+ }
+ }
+ close(CMD);
+}
+
+$ENV{'ip'} = $ip;
+$ENV{'port'} = $port;
+
+if(defined $ARGV[0] and $ARGV[0] eq "config") {
+ config();
+} else {
+ fetch();
+}
+
+# vim: ts=4:ai:et:syntax=perl

0 comments on commit 32c46a3

Please sign in to comment.