#!/usr/bin/perl 
# nagios: +epn

=head1 NAME 

check_jmx4perl - Nagios check using jmx4perl for accessing JMX information 

=head1 SYNOPSIS 

 # Check used heap memory for absolute values
 check_jmx4perl --url http://localhost:8888/j4p \
                --name memory_used \
                --mbean java.lang:type=Memory \
                --attribute HeapMemoryUsage \ 
                --path used \
                --critical 10000000 \
                --warning   5000000 

 
 # Check for string values by comparing them literally
 check_jmx4perl --url http://localhost::8888/j4p \
                --mbean myDomain:name=myMBean \
                --attribute stringAttribute \
                --string \
                --critical 'Stopped' \
                --warning '!Started'

 # Check used heap memory for absolute values by using an alias
 check_jmx4perl --url http://localhost:8888/j4p \
                --alias MEMORY_HEAP_USED \
                --critical 10000000 \
                --warning   5000000 

 # Check that the used heap memory is below 80% of the available memory
 check_jmx4perl --url http://localhost:8888/j4p \
                --alias MEMORY_HEAP_USED \
                --base MEMORY_HEAP_MAX \ 
                --critical :80

 # Check that no more than 5 threads are started in a minute
 check_jmx4perl --url http://localhost:8888/j4p \
                --alias THREAD_COUNT_STARTED \
                --delta 60 \
                --critical 5

 # Execute a JMX operation on an MBean and use the return value for threshold
 check_jmx4perl --url http://localhost:8888/j4p \
                --mbean jmx4perl:type=Runtime \
                --operation getNrQueriesFor \
                --critical 10 \
                "operation" \
                "java.lang:type=Memory" \
                "gc" 

 # Use check_jmx4perl in proxy mode
 check_jmx4perl --url http://localhost:8888/j4p \
                --alias MEMORY_HEAP_USED \
                --critical 10000000 \
                --target service:jmx:rmi:///jndi/rmi://bhut:9999/jmxrmi
  
 # Use predefined checks in a configuration file with a server alias
 # Server alias is 'webshop', check is about requests per minute for the 
 # servlet 'socks_shop'
 check_jmx4perl --config /etc/nagios/check_jmx4perl/tomcat.cfg
                --server webshop \
                --check tc_servlet_requests \
                --critical 1000 \
                socks_shop

=head1 DESCRIPTION

Nagios plugin for monitoring Java applications which expose JMX data via a
jmx4perl agent.

This plugin can be used in two ways: First, all required parameters for
identifying the JMX information can be given via the command line. Second, a
configuration file can be used to define one or more nagios checks. This is the
recommend mode, since it allows for more advanced features not available when
using the command line alone. Each command line argument has an equivalent
configuration option.

Before we describe the w

=head1 BASICS

=head1 MBeans

JMX's central entity is an E<MBean>. An MBean exposes management information in
a well defined way. Each MBean has a unique name with the following structure:

  domain:attribute1=value1,attribute2=value2, .....

E.g.

  java.lang:type=Memory

Before you start monitoring, you need to know the MBean name. There are various
ways to identify the MBean:

=over 

=item * 

Use C<jmx4perl --list> to list all registered MBeans. In addition C<jmx4perl
--attributes> dumps out all known MBean attributes along with their values. 
(Be careful, the output can be quite large)

=item *

Use C<j4psh> for interactively exploring the JMX namespace.

=item *

Use an alias. An alias is a shortcut for an MBean name, predefined by
L<JMX::Jmx4Perl>. All known aliases can be shown with C<jmx4perl>.  Since each
platform can have slightly different MBean names for the same information, this
is extra level of indirection might help in identifying MBeans. See below for
more about aliases.

=item *

Use a predefined check. C<check_jmx4perl> comes with quite some checks
predefined in various configuration files. These are ready for use out of the
box. 

=item *

As your Java application development team for application specific MBean names. 

=back.


=head2 Operational Modes

C<check_jmx4perl> can obtain the information to monitor from two sources:
Either as MBean I<attributes> or as return value from JMX I<operations>.  Since
JMX values can be any Java Object, it is important to understand, how
C<check_jmx4perl> (or JMX::Jmx4Perl in general) handles this situation.

Simple data types can be used directly in threshhold checking. I.e. the
following data types can be used directly

=over

=item Integer

=item Long

=item Float

=item Double

=item Boolean

=item String

=back

C<String> and C<Boolean> can be used in I<string> checks only, whereas the others
can be used in both, I<numeric> and I<string> checks.


=head3 Pathes

For more complex types, C<check_jmx4perl> provides the concept of so called
I<pathes> for specifying an inner attribute of a more complex attribute or
operation return value. A path is build of parts, separated by slashes
(/). It's simplified variant of an XPath expression for accessing parts of an
XML document. Each part points to an level of the JSON serialized object. 

For example, the MBean C<java.lang:type=Memory> exposes an attribute called
C<HeapMemoryUsage>. This attribute is a combound data type, which contains
multiple entries. Looking with C<jmx4perl> at this attribute

 $ jmx4perl http://localhost:8080/j4p read java.lang:type=Memory HeapMemoryUsage
 $VAR1 = {
           'committed' => '85000192',
           'used' => '8135440',
           'max' => '129957888',
           'init' => '0'
         };

one sees, that there are 4 values coming with the reponse. With a path C<used>
one can directly pick the used heap memory usage (8135440 bytes in this case)
which can be used in a threshold check. This path can be used with
C<check_jmx4perl> like 

 $ check_jmx4perl --url http://localhost:8080/j4p \ 
                  --mbean java.lang:type=Memory \ 
                  --attribute HeapMemoryUsage \
                  --path used \
                  --critical 100000000
 OK - [java.lang:type=Memory,HeapMemoryUsage,used] : Value 10136056 in range | ...
1
=head3 Attributes

Attribute are values which can be obtained from MBeans. They can be of a simple
data type like a string or an integer, but they can be arbitrarly complex (e.g
an arbitrary Java type). Simple data types can be used directly for threshold
checking where the value is compared against a critical or warning threshold
directly. 




-- Values
-- 

=head3 Operations


=head2 Aliases

=head2 Relative Checks

=head2 Incremental Checks

=head2 Output Tuning

=head2 Proxy mode
 
=head1 COMMAND LINE 

The pure command line interface (without a configuration file) is mostly suited
for simple checks where the predefined defaults are suitable. For all other use
case, a configuration file fits better. 

=head2 Command Line Options




Command for providing Nagios conmpliant output for JMX response fetched via
L<JMX::Jmx4Perl>. It knows about critical (via C<--critical>) and warning (via
C<--warning>) thresholds. 

You can also use direct string comparison. In this case C<--critical> and
C<--warning> are not treated as numerical values but as string types. They are
compared literally against the value retrieved and yield the corresponding
Nagios status if matched. If the threshold is given with a leading C<!>, the
condition is negated. E.g. a C<--critical '!Running'> given returns a
C<CRITICAL> if the value is I<not> equals to C<Running>. As a final option you
can also use a regular expression by using C<qr/.../> as threshold value
(substitute C<...> with the pattern to used for comparison). Boolean values are
returned as C<true> or C<false> strings from the agent, so you can check for
them as well with this kind of string comparison.

Whether string comparison or a numerical check is used is determined
automatically based on the value returned. You can enforce a particular mode by
providing the option C<--numeric> or C<--string> respectively.

Values obtained from the server can be interpreteted as relative values when
C<--base> is given. The argument provided here is first tried as an alias name
or checked as an absolute, numeric value. Alternatively, you can use a full
MBean/Attribute/Path specification by using a C</> as separator, e.g. 

  ... --base java.lang:type=Memory/HeapMemoryUsage/max ...

If one of these parts (the path is optional) contains a slash within its name,
the part must be URI encoded. I.e. all parts are URI decoded before usages as
naming pattern. In any case, using an alias or direct MBean names, the base
value is fetched first for calculating the relative value. For a numeric value
given here this is of course not necessary.

C<--delta> switches on incremental mode in which the difference between two
following values is used. The optional argument are interpreted as seconds
which are used for calculating the speed of growth. If not given, only the
difference between the current and the latest value is taken. C<--delta>
doesn't work with C<--base>.

With the option C<--operation> a JMX operation is triggered and the return
value used for threshold calculations. Additionally, if use an operation
alias with C<--alias>, you can ommit C<--operation> and C<--mbean>. Any
arguments required for the operation need to be provided as additional
arguments. 

The output of C<check_jmx4perl> can be highly customized. First of all, you can
provide a unit-of-measurement with the option C<--unit>. This specifies how the
the attribute or an operation's return value should be interpreted. The
units available are

  B  - Byte
  KB - Kilo Byte
  MB - Mega Byte
  GM - Giga Byte
  TM - Terra Byte
  
  us - Microseconds
  ms - Milliseconds
  s  - Seconds
  m  - Minutes
  h  - Hours
  d  - Days

The unit will be used for performance data as well as for the plugin's
output. Large numbers are converted to larger units (and reverse for small
number that are smaller than 1). E.g. C<2048 KB> is converted to C<2
MB>. However, beautifying by conversion is I<only> performed for the plugin
output, B<not> for the performance data for which no conversions happens at all.

Beside unit handling, you can provide your own label for the Nagios output via
C<--label>. The provided option is interpreted as a pattern with the following
placeholders: 

 %v   the absolute value 
 %f   the absolute value as floating point number
 %r   the relative value for relative calculations (--base)
 %u   the value's unit for the output when --unit is used
 %w   the the base value's for the output unit when --unit is used
 %b   the absolut base value as it is used with --base 
 %c   the Nagios exit code in the Form "OK", "WARNING", "CRITICAL" 
      or "UNKNOWN"
 %t   Threshold value which fails ("" when the check doesn't fail)
 %n   name, either calulated automatically or given with --name
 %d   the delta value used for normalization when using incremental mode

Note that C<%u> and C<%w> are typically I<not> the same as the C<--unit>
option. They specify the unit I<after> the conversion for the plugin output as
described above. You can use the same modifiers as for C<sprintf> to fine tune
the output.

Example: 

 check_jmx4perl --url http://localhost:8888/j4p \
                --alias MEMORY_HEAP_USED \
                --base MEMORY_HEAP_MAX \ 
                --critical :80 \
                --label "Heap-Memory: %.2r% used (%.2v %u / %.2b %u)" \
                --unit B

will result in an output like

 OK - Heap-Memory: 3.48% used (17.68 MB / 508.06 MB) | '[MEMORY_HEAP_USED]'=3.48%;;:80

C<check_jmx4perl> can be used in a proxy mode as well. When the option
C<--target> is given, the agent servlet use this url as a JMX Service URL and
tries to connect via a JSR-160 to specified target to obtain the JMX
information from there. Additionally C<--target-user> and C<--target-password>
can be used to provide credentials if the target server is secure with user-
and password name. Please see the manual for more information about the proxy
mode and its limitations.

=head1 CONFIGURATION

=head2 Multichecks

=head2 Parent checks

=head2 Parameterized checks

=head2 Predefined checks



=cut

use FindBin qw ($Bin);
# Used for running directly out of the distrib dir,
# but we put the lib at last to avoid security issues
# on a proper installed system
#BEGIN { push(@INC, qq($Bin/../lib)); }
use lib qq($Bin/../lib);
use Nagios::Plugin::Functions;
use JMX::Jmx4Perl::Nagios::CheckJmx4Perl;

# Hack for avoiding a label in front of "OK" or "CRITICAL", in order to conform
# to the usual Nagios conventions and to use redundancy in the UI display.
BEGIN {
    no warnings 'redefine';
    *Nagios::Plugin::Functions::get_shortname = sub {
        return undef;
    };
}

# Create new object and use this for the check
# Hopefully it gets cleaned up aftewards if running
# within the embedded Nagios perl interpreter. At least, 
# we don't keep any references
JMX::Jmx4Perl::Nagios::CheckJmx4Perl->new(@ARGV)->execute();

=head1 LICENSE

This file is part of jmx4perl.

Jmx4perl 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.

jmx4perl 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 jmx4perl.  If not, see <http://www.gnu.org/licenses/>.

=head1 AUTHOR

roland@cpan.org

=cut
