#!/usr/bin/perl

#
#  Author: Matt Judge
#    Date: 23/09/08
#    Desc: Utility to check the status of an instance of Tomcat running on the localhost
#

use strict;
use Getopt::Long;

# Nagios stuff
use lib "/usr/lib64/nagios/plugins";
use utils qw (%ERRORS &print_revision &support);

# Pretty stuff
use Term::ANSIColor qw(uncolor);
use Term::ANSIColor qw(:constants);
$Term::ANSIColor::AUTORESET=1;

my ($opt_d, $opt_h, $opt_m, $opt_p, $opt_t);
GetOptions ( "d=i" => \$opt_d, "debug"           => \$opt_d,
             "h=s" => \$opt_h, "host"            => \$opt_h,
             "p=i" => \$opt_p, "port"            => \$opt_p,
             "m=i" => \$opt_m, "percent_mem"     => \$opt_m,
             "t=i" => \$opt_t, "percent_threads" => \$opt_t);

$opt_m = 80 unless defined ($opt_m);
$opt_t = 80 unless defined ($opt_t);
$opt_h = "localhost" unless defined ($opt_h);
$opt_p = 9080 unless defined ($opt_p);

#
# URL for the Apache Tomcat status (including login details)
my $status_url  = "http://nagios:nagios\@${opt_h}:${opt_p}/manager/status";

#
# Test URL, provided by the dev team
my $test_url    = "http://localhost:9080/Pdf/monitor";

#
# I didn't want to use wget, but it seems the easiest way.
my $wget = "/usr/bin/wget --no-proxy -q -O -";

my %memory = ( free => 0, total => 0, max => 0 );

my %engine = ();
my $engine = "";

my $cmd = "$wget $status_url";
open INP, "$cmd |";
while (<INP>)
{
  # GRRRR.  The output gets sent in one line so I need to break the output
  # into manageable sections.
  my @lines = split(/<\/tr>/);

  foreach $_ (@lines)
  {
    # Strip HTML tags and replace them with '*'
    $_ =~ s/\<[^\<]+\>/*/g;

    # Skip blank lines or lines only containing one or more '*'
    next if (/^\s*[\*]*\s*$/);

    # Replace multiple '*' with just one
    $_ =~ s/\*\*+/\*/gxms;

    print "$_\n" unless $opt_d < 8;

    # Free memory: 61.56 MB Total memory: 77.12 MB Max memory: 951.43 MB
    if ( /Free memory:\s+(\S+)\s+(.B)\s+Total Memory:\s+(\S+)\s+(.B)\s+Max Memory:\s+(\S+)\s+(.B)/i )
    {
      print "     Memory: [" . YELLOW . "$1" . RESET . "][$2][" . YELLOW . "$3" . RESET . "][$4][" . YELLOW . "$5" . RESET . "][$6]\n" unless $opt_d < 1;

      %memory->{'free'}         = $1;
      %memory->{'total'}        = $3;
      %memory->{'max'}          = $5;
    }

    # *jk-8009* Max threads: 200 Min spare threads: 4 Max spare threads: 50 Current thread count: 104 Current thread busy: 102
    if ( /\*(\S+)\* Max threads:\s+(\d+)\s+Min\s+.*:\s+(\d+)\s+Max.*:\s+(\d+)\s+Current.*busy:\s+(\d+)/i )
    {
      $engine = $1;

      print "    Threads: [" . GREEN . $engine . RESET . "][" . CYAN . $2 . RESET . "][$3][$4][" . GREEN . $5 . RESET . "]\n" unless $opt_d < 1;

      $engine{$engine}->{'threads'}->{'max'}         = $2;
      $engine{$engine}->{'threads'}->{'min_spare'}   = $3;
      $engine{$engine}->{'threads'}->{'max_spare'}   = $4;
      $engine{$engine}->{'threads'}->{'busy'}        = $5;
    }

    # Max processing time: 0 ms Processing time: 0.0 s Request count: 0 Error count: 0 Bytes received: 0.00 MB Bytes sent: 0.00 MB
    if ( /Max processing time: (\S+) (\S+) Processing time: (\S+) (\S+) Request count: (\d+) Error count: (\d+) .* Bytes sent: (\S+) ([A-z]+)/i )
    {
      print " Processing: [" . GREEN . $engine . RESET . "][$1][$2][$3][$4][" . GREEN . $5 . RESET . "][$6][" . GREEN . $7 . RESET . "][$8]\n" unless $opt_d < 1;

      $engine{$engine}->{'requests'}->{'max_time'}   = $1;
      $engine{$engine}->{'requests'}->{'total_time'} = $2;
      $engine{$engine}->{'requests'}->{'count'}      = $3;
      $engine{$engine}->{'requests'}->{'errors'}     = $4;
      $engine{$engine}->{'requests'}->{'bytes_sent'} = $5;
    }

    # *S*135714 ms*327 KB*0 KB*130.88.0.58*pdfserve.informaworld.com*GET /Pdf/AddCoversheet?xml=/mnt/pdfserve/pdfserve/552826-751310453-795187286.xml HTTP/1.1*
    # *K*79900 ms*?*?*192.148.223.119*?*?*
    # *S*36086 ms*199 KB*0 KB*80.255.43.116*pdfserve.informaworld.com*GET /Pdf/AddCoversheet?xml=/mnt/pdfserve/pdfserve/704391-788608932-739378072.xml HTTP/1.0*
    #          K     79900     ms     ?
    if ( /\*([A-z])\*(\d+)\s+([^\*]*)\*([^\*]*)\*([^\*]*)\*([^\*]*)\*([^\*]*)\*([^\*]*)\*/ )
    {
      print "     Thread: [" . CYAN . $1 . RESET . "][$2][$3][$4][$5][$6][$7][$8]\n" unless $opt_d < 2;
    }
  }
}

#
# Predefine our variables
#
my $result = "";
my $mesg   = "";

#
# Check the test URL to see if it is acessible
my $cmd = "$wget $test_url";
open INP, "$cmd |";
while (<INP>)
{
  if ( /PDF Serve Status: 200/ )
  {
    $result = "OK";
  }
}
close (INP);

if ( $result !~ /^OK$/ )
{
  $result = "CRITICAL";
  $mesg  .= "Could not poll: /Pdf/monitor";
}

# Calculate the percentage of available memory
if ( %memory->{'max'} )
{
  my $pct_memory  = scalar( ((%memory->{'total'} - %memory->{'free'}) * 100) / %memory->{'max'});
  if ( $pct_memory > $opt_m )
  {
    $mesg   .= ($mesg ? ", " : "") . sprintf "Memory usage is at %.2f%%", $pct_memory;
    $result  = "CRITICAL";
  }

   #
   # Show 'em the memory usage
  $mesg .=  ($mesg ? ", " : "") . sprintf "[Using %.2fMB of %.2fMB RAM]", (%memory->{'total'} - %memory->{'free'}), %memory->{'max'};

  foreach my $engine (keys(%engine))
  {
    # Calculate the percentage of used threads
    my $pct_threads = scalar( ($engine{$engine}->{'threads'}->{'busy'} * 100) / $engine{$engine}->{'threads'}->{'max'} );

    if ( $pct_threads > $opt_t )
    {
      $mesg   .= ($mesg ? ", " : "") . sprintf ">> %s is using %.2f%% of the available threads", $engine, $pct_threads;
      $result  = "CRITICAL";
    }

    # Assuming all memory is defined in MB
    $mesg .=  ($mesg ? "; " : "") . sprintf "%s %d of %d available threads in use", $engine,
              $engine{$engine}->{'threads'}->{'busy'}, $engine{$engine}->{'threads'}->{'max'};
  }
}
else
{
  $result = "CRITICAL";
  $mesg  .= "Not able to determine server information";
}

print "TOMCAT $result: $mesg\n";
exit $ERRORS{$result};


