#!/usr/bin/perl
#
# (c)2001 Sebastian Hetze, Linux Information Systems AG
# send bug reports to <S.Hetze@Linux-AG.com>
# 
#
# This program has been edited by Janet Post to work with apache 2
# server status format and for specific Excapsa apache settings.
#
# 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 (or with Nagios);  if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA
#
#
# Check apache status information provided by mod_status to find
# out about the load (number of servers working) and the
# performance (average response time for recent requests).
#
# Usage:
# check_apache -H <host> [-lhiV] [-w <warn>] [-c <crit>] [-u <url>]
#
# check_apache <host> <warn> <crit> <url> (if you cannot avoid it)
#

## This editted version of check_apache expects:   check_apache -H <host> -i -w <warn> -c <crit>
#  if you omit the -i it will only display the list of variables I was looking for for debugging purposes.
#  I left it in the code so I could easily test later when I want more information out of the server status page

use LWP::UserAgent;
use URI::URL;
use Getopt::Long;
Getopt::Long::Configure('bundling');

$version=0.01;

my %ERRORS = ('UNKNOWN' , '-1',
              'OK' , '0',
              'WARNING', '1',
              'CRITICAL', '2');


#
#              some default values
#
$perf_w=500;
$perf_c=1000;
$load_w=20;
$load_c=30;
$TIMEOUT=15;

#
#              get command line options the regular way
#
GetOptions
        ("V"   => \$opt_V, "version"       => \$opt_V,
         "h"   => \$opt_h, "help"          => \$opt_h,
	 "i"   => \$opt_i, "idle"          => \$opt_i,
         "l"   => \$opt_l, "load"          => \$opt_l,
         "v" => \$verbose, "verbose"       => \$verbose,
         "w=s" => \$opt_w, "warning=s"     => \$opt_w,
         "c=s" => \$opt_c, "critical=s"    => \$opt_c,
         "H=s" => \$opt_H, "hostname=s"    => \$opt_H,
         "u=s" => \$opt_u, "url=s"         => \$opt_u);

#
#              handle the verbose stuff first
#
if ($opt_V) {
        print "\n";
        print "check_apache nagios plugin version $version\n";
        print "\n";
        print "The nagios plugins come with ABSOLUTELY NO WARRANTY.  You may redistribute\n";
        print "copies of the plugins under the terms of the GNU General Public License.\n";
        print "For more information about these matters, see the file named COPYING.\n";
        print "\n";
        print "Copyright (c) 2001 Sebastian Hetze  Linux Information Systems AG\n";
        print "\n";
        print "\n";
        exit $ERRORS{'UNKNOWN'};
} 

if ($opt_h) {
        print_help();
        exit $ERRORS{'UNKNOWN'};
}

#
#              now get options the weired way and set the defaults
#              if nothing else is provided
#
$opt_H = shift unless ($opt_H);
print_usage() unless ($opt_H);

if($opt_l) {
   $autostring="?auto";
   ($opt_w) || ($opt_w = shift) || ($opt_w = $load_w);
   $warn = $1 if ($opt_w =~ /([0-9]+)/);
   ($opt_c) || ($opt_c = shift) || ($opt_c = $load_c);
   $alert = $1 if ($opt_c =~ /([0-9]+)/);
} else {
   $autostring="";
   ($opt_w) || ($opt_w = shift) || ($opt_w = $perf_w);
   $warn = $1 if ($opt_w =~ /([0-9]+)/);
   ($opt_c) || ($opt_c = shift) || ($opt_c = $perf_c);
   $alert = $1 if ($opt_c =~ /([0-9]+)/);
}

($opt_u) || ($opt_u = shift) || ($opt_u = "/server-stat");


#
#              dont let us wait forever...
#
$SIG{'ALRM'} = sub {
     print ("ERROR: No response from HTTP server (alarm)\n");
     exit $ERRORS{"UNKNOWN"};
};
alarm($TIMEOUT);


#
#              now we set things up for the real work
#              and fire up the request
#
$ua = new LWP::UserAgent;
$ua->agent("Nagios/0.1 " . $ua->agent);


$urlstring = "http://" . $opt_H . $opt_u . $autostring;
$url = url($urlstring);

my $req = new HTTP::Request 'GET', $url;
my $res = $ua->request($req);

#
#              hopefully we´ve got something usefull
#
if ($res->is_success) {
    foreach $_ (split /^/m, $res->content) {
        next if /^\s*$/;
#
#              this is the load checking section
#              we parse the whole content, just in case someone
#              wants to use this some day in the future
#
        if (/^Total Accesses:\s+([0-9.]+)/) { $accesses = $1; }
        if (/Total Traffic:\s+([0-9.]+)/) { $kbytes = $1; next; }
        if (/Server uptime:\s+(.+)</) { $uptime = $1; next; }
        if (/([0-9.]+) requests\/sec/) { $rps = $1; }
        if (/\s+([0-9.]+) kB\/second/) { $bps = $1; }
        if (/([0-9.]+) B\/request/) { $bpr = $1; next; }
        if (/([0-9.]+) requests currently/) { $busy = $1; }
        if (/([0-9.]+) idle/) { $idle = $1; next; }
        if (/^Scoreboard:\s+([SRWKDLG_.]+)\s+/) { $score = $1; next; }
        next;
    }

    my $idlepercent = $busy + $idle;

    if($opt_i) {
	if($idlepercent<$alert) {
	    printf "HTTPD CRITICAL: only %.0f servers idle (%d idle)\n", $idle, $idlepercent;
	    exit $ERRORS{"CRITICAL"};
	}
	if($idlepercent<$warn) {
	    printf "HTTPD WARNING: only %.0f servers idle (%d idle)\n", $idle, $idlepercent;
	    exit $ERRORS{"WARNING"};
	}
	printf "HTTPD ok: %.0f servers running, %d idle\n", $busy, $idle;
	exit $ERRORS{"OK"};
	
    } 

########  The following is removed temporarily as I do not need any of it's functions -- yet
#
#              now we even parse the whole scoreboard, just for fun
#


#     foreach $scorepoint (split //m, $score) {
#        if($scorepoint eq '.') { $scores{'.'}+=1; next; }  # Unused
#        if($scorepoint eq '_') { $scores{'_'}+=1; next; }  # Waiting
#        if($scorepoint eq 'S') { $scores{'S'}+=1; next; }  # Starting
#        if($scorepoint eq 'R') { $scores{'R'}+=1; next; }  # Reading
#        if($scorepoint eq 'W') { $scores{'W'}+=1; next; }  # Writing
#        if($scorepoint eq 'K') { $scores{'K'}+=1; next; }  # Keepalive
#        if($scorepoint eq 'D') { $scores{'D'}+=1; next; }  # DNS Lookup
#        if($scorepoint eq 'L') { $scores{'L'}+=1; next; }  # Logging
#        if($scorepoint eq 'G') { $scores{'G'}+=1; next; }  # Going
#     }
#
#     if($busy>$alert) {
#        printf "HTTPD CRITICAL: %.0f servers running\n", $busy;
#	exit $ERRORS{"CRITICAL"};
#     }
#     if($busy>$warn) {
#        printf "HTTPD WARNING: %.0f servers running\n", $busy;
#	exit $ERRORS{"WARNING"};
#     }
#     printf "HTTPD ok: %.0f servers running, %d idle\n", $busy, $idle;
#     exit $ERRORS{"OK"};
#
#  } else {
##
##              this is the performance check section
##              We are a bit lazy here, no parsing of the initial data
##              block and the scoreboard.
##              However, you have the whole set of per server
##              information to play with ;-)
##              The actual performance is measured by adding up the
##              milliseconds required to process the most recent
##              requests of all instances and then taking the average.
##
#     foreach $tablerow (split /<tr>/m, $res->content) {
#         ($empty,$Srv,$PID,$Acc,$M,$CPU,$SS,$Req,$Conn,$Child,$Slot,$Client,$VHost,$Request)
#         = split /<td>/, $tablerow;
#         if($Req) {
#              $lines+=1;
#              $req_sum+=$Req;
#         }
#         undef $Req;
#     }
#     $average=$req_sum/$lines;
#     if($average>$alert) {
#        printf "HTTPD CRITICAL: average response time %.0f
#	milliseconds\n", $average;
#	exit $ERRORS{"CRITICAL"};
#     }
#     if($average>$warn) {
#        printf "HTTPD WARNING: average response time %.0f
#	milliseconds\n", $average;
#	exit $ERRORS{"WARNING"};
#     }
#     if($average>0) {
#        printf "HTTPD ok: average response time %.0f milliseconds\n",
#        $average;
#        exit $ERRORS{"OK"};
#     }
#     print "Unknown Status\n";
#     exit $ERRORS{"UNKNOWN"};
#  }
#} else {
#	print "HTTP request failed\n";
#	exit $ERRORS{"CRITICAL"};
#}
#
#
#
#              ok, now we are almost through
#              These last subroutines do the things for those that do not
#              read source code.
#

############ end of temporarily removed section.

# This section is for testing purposes -- the program will normally exit natural before this point
#  if the -i option is choosen.  This is so I can see the variables and make sure I collecting the RIGHT data.

     print "busy: $busy\n";
     print "idle: $idle\n";
     print "bpr: $bpr\n";
     print "bps: $bps\n";
     print "rps: $rps\n";
     print "uptime: $uptime\n";
}


sub print_usage () {
        print "Usage: $0 -H <host> [-lihV] [-w <warn>] [-c <crit>] [-u <url>]\n"; }
 
sub print_help () {
        print "\n";
        print "\n";
        print "check_apache nagios plugin version $version\n";
        print "\n";
        print "The nagios plugins come with ABSOLUTELY NO WARRANTY.  You may redistribute\n";
        print "copies of the plugins under the terms of the GNU General Public License.\n";
        print "For more information about these matters, see the file named COPYING.\n";
        print "\n";
        print "Copyright (c) 2001 Sebastian Hetze  Linux Information Systems AG\n";
        print "\n";
        print "\n";
        print "This plugin checks the apache HTTP service on the specified host.\n";
        print "It uses the mod_status facilities provided by the apache server.\n";
        print "The monitoring server must be authorized in httpd.conf.\n";
        print "\n";
        print "\n";
        print_usage();
        print "\n";
        print "Options:\n";
        print " -H, --hostname=ADDRESS\n";
        print "     host name argument for server.\n";
        print " -l, --load\n";
	  		print "     check load instead of performance.\n";
        print " -h, --help\n";
				print "     print detailed help screen.\n";
				print " -i, --idle\n";
				print "     check idle threads instead of performance.\n";
        print " -V, --version\n";
				print "     print version information.\n";
        print " -w, --warning=INTEGER\n";
        print "     load / performance level at which a warning message will be gererated.\n";
        print " -c, --critical=INTEGER\n";
        print "     load / performance level at which a critical message will be gererated.\n";
        print " -u, --url=PATH\n";
        print "     location to call mod_status.\n";
        print "\n";
        print "     Defaults for performance checking are $perf_w/$perf_c msec.\n";
        print "     Defaults for load checking are $load_w/$load_c servers running.\n";
        print "\n";
        print "\n";
} 
#
#              the end
#
