#
# check_jmxproxy
#
# Contacts a JMX proxy (like that which Apache Tomcat provides)
# and compares the return value to the warning and critical values
# provided as parameters to this script.
#
# Copyright (c) 2012 Christopher Schultz
#
# Christopher Schultz licenses this file to You under the Apache License,
# Version 2.0 (the "License"); you may not use this file except in
# compliance with the License.  You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#
# Special thanks to Susan Burgee for her help with Perl.
#

use strict;

# For getopt:
use Getopt::Long qw(:config no_ignore_case bundling);;

# For HTTP stuff:
use LWP::UserAgent;
use HTTP::Request;
use HTTP::Response;
use URI::Heuristic;

my $help     = '';
my $url      = '';
my $warn     = '';
my $critical = '';
my $verbose = '';
my $authorization = '';
my $useragent = 'Nagios check_jmxproxy/0.1';
my $timeout = 180;
my $fetchingRegexp = '^OK.*=\s*([0-9]+)$';
# $fetchingRegexp = 'OK.*used=([0-9]+).*';
my $outputFilterRegexp;

GetOptions(
    'U=s'             => \$url,
    'url=s'           => \$url,
    'w=s'             => \$warn,
    'warn=s'          => \$warn,
    'c=s'             => \$critical,
    'critical=s'      => \$critical,
    'h'               => \$help,
    'help'            => \$help,
    'v'               => \$verbose,
    'verbose'         => \$verbose,
    'a=s'             => \$authorization,
    'authorization=s' => \$authorization,
    'A'               => \$useragent,
    'useragent'       => \$useragent,
    't=i'             => \$timeout,
    'timeout=i'       => \$timeout,
    'r=s'             => \$fetchingRegexp,
    'regexp=s'        => \$fetchingRegexp,
    'R=s'             => \$outputFilterRegexp,
    'filtering-regexp=s' => \$outputFilterRegexp,
) or $help = '-h';

$help = 1 if ( $url eq '' || $warn eq '' || $critical eq '' );

if( $help ) {
    print <<USAGE;
Usage: $0 [-v] [-a auth] [-A agent] -U <url> -w <warn> -c <critical>

  -A, --useragent
    Specify the User-Agent that will be sent when contacting the server.

  -a, --authorization
    Specify the BASIC authorization string that will be used to satisfy
    a WWW-Authenticate challenge. Should be in the form 'user:password'.

  -c, --critical
    Specifies the 'critical' level against which the number returned
    from the JMX proxy will be compared. Append a ':' to the end of
    the critical value in order to perform a less-than comparison.

  -h, --help
    Shows this help message.

  -r, --regexp
    Specifies the regular expression that will be used to capture the
    numeric portion of the JMX proxy's response. The first capture group
    in the regular expression will be used as the numeric response.
    Default: '^OK.*=\\s*([0-9]+)\$'

  -R, --filtering-regexp
    Specifies the regular expresison that will be used to filter the
    response from the JMX proxy before echoing it to the output stream
    after a "JMX OK", "JMX WARN", or "JMX CRITICAL" message. If the
    response from the JMX proxy is malformed, the response will not be
    filtered.

  -t, --timeout
    Specifies the timeout, in seconds, to wait for a response before
    the request to the server is considered a failure. Default is 180
    (3 minutes).

  -U, --url
    Specifies the URL that check_jmxproxy will contact.

  -v, --verbose
    Enabled verbose logging of what check_jmxproxy is doing.

  -w, --warn
    Specifies the 'warning' level against which a number returned
    from the JMX proxy will be compared. Append a ':' to the end of
    the warning value in order to perform a less-than comparison.

Example:
   ${0} -U 'http://host/manager/jmxproxy?get=java.lang:type=Memory&att=HeapMemoryUsage&key=used' -w 33554432 -c 50331648

  This example will report CRITICAL if the current JVM heap size exceeds
  48MiB or WARN if the heap size exceeds 32MiB.
USAGE
    exit();
}

if ($verbose) {
  print "url = $url\n" if ($url);
  print "cricital = $critical\n" if ($critical);
  print "warn = $warn\n" if ($warn);
}

my $full_url = URI::Heuristic::uf_urlstr($url);
my $ua = LWP::UserAgent->new();
$ua->agent($useragent);
my $req = HTTP::Request->new(GET => $url);

# Set the authentication information if necessary
if (!($authorization eq '')) {
  $req->authorization_basic(split /:/, $authorization, 2);
}

$ua->timeout($timeout);

my $response = $ua->request($req);

if ($response->is_error()) {
  printf "JMX CRITICAL: Response: %s\n", $response->status_line;
  exit 2;
} else {
  my $content = $response->content();

  # Remove any trailing newlines
  chomp($content);

  if($verbose) {
    print "(v) Using fetching regexp '$fetchingRegexp'\n";
  }
  my($num) = ($content =~ /$fetchingRegexp/);

  if($verbose) {
    print "(v) Response from JMX proxy: '$content'\n";
    print "(v) got number from JMX: $num\n";
  }

  if($num eq '') {
    printf "JMX CRITICAL: Bad Response: %s\n", $content;
    exit 2;
  } else {
    if($outputFilterRegexp) {
      print "Filtering JXM proxy response using filter: $outputFilterRegexp" if $verbose;
      ($content) = $content =~ /$outputFilterRegexp/;
    }

    if ($critical =~ /:$/) {
      printf "(v) checking if %s < %s (critical)\n", $num, $critical if $verbose;

      if($num < $critical) {
        print "(v) $num < $critical\n" if $verbose;
        printf "JMX CRITICAL: %s\n", $content;
        exit 2;
      } elsif ($warn =~ /:$/) {
        printf "(v) checking if %s < %s (warn)\n", $num, $warn if $verbose;

        if($num < $warn) {
          print "(v) $num < $warn\n" if $verbose;

          printf "JMX WARN: %s\n", $content;
          exit 1;
        } else {
          print "(v) $num > $warn\n" if $verbose;

          printf "JMX OK: %s\n", $content;
        }
      } elsif ($num > $warn) {
        print "(v) $num > $warn\n" if $verbose;

        printf "JMX WARN: %s\n", $content;
        exit 1;
      } else {
        print "(v) $num < $warn\n" if $verbose;

        printf "JMX OK: %s\n", $content;
      }
    } else {
      if($num > $critical) {
        print "(v) $num > $critical\n" if $verbose;

        printf "JMX CRITICAL: %s\n", $content;
        exit 2;
      } elsif ($warn =~ /:$/) {
        if($num < $warn) {
          print "(v) $num < $warn\n" if $verbose;

          printf "JMX WARN: %s\n", $content;
          exit 1;
        } else {
          print "(v) $num > $warn\n" if $verbose;

          printf "JMX OK: %s\n", $content;
        }
      } elsif ($num > $warn) {
        print "(v) $num > $warn\n" if $verbose;

        printf "JMX WARN: %s\n", $content;
        exit 1;
      } else {
        print "(v) $num < $warn\n" if $verbose;

        printf "JMX OK: %s\n", $content;
      }
    }
  }
}

tools/check_jmxproxy.pl (last edited 2014-03-18 20:08:08 by ChristopherSchultz)