#!/usr/bin/perl
#
# (c) 2006 Ulrich Wisser, Relevant Traffic AB
#          ulrich.wisser@relevanttraffic.com
#
# Derived work from:
#
# (c)2001 Sebastian Hetze, Linux Information Systems AG
# send bug reports to <S.Hetze@Linux-AG.com>
#
# Some fixes by Rob.
#
# 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; version 2
# of the License
#
# 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).
#
use strict;
use LWP::UserAgent;
use URI::URL;
use Getopt::Long;
Getopt::Long::Configure('bundling');
use vars qw($VERSION);

$VERSION=0.01;

my %ERRORS = ('UNKNOWN' , '-1',
              'OK' ,       '0',
              'WARNING',   '1',
              'CRITICAL',  '2');
#
# global default values
#
my $perf_w=500;
my $perf_c=1000;
my $load_w=80;
my $load_c=100;
my $timeout=15;
my $autostring="?auto";
#
# get command line options the regular way
#
my ($opt_V, $opt_h, $opt_l, $opt_w, $opt_c, $opt_H, $opt_u, $verbose);
GetOptions(
    "V"   => \$opt_V,   "version"    => \$opt_V,
    "h"   => \$opt_h,   "help"       => \$opt_h,
    "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_perf 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";
    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
#
if (!$opt_H) {print_usage(); exit $ERRORS{'UNKNOWN'}; };
if (!$opt_u) {print_usage(); exit $ERRORS{'UNKNOWN'}; };
my $warn  = $1 if ($opt_w =~ /([0-9]+)/);
my $alert = $1 if ($opt_c =~ /([0-9]+)/);
if (!$warn)  {print_usage(); exit $ERRORS{'UNKNOWN'}; };
if (!$alert) {print_usage(); exit $ERRORS{'UNKNOWN'}; };



#
# 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
#
my $ua  = new LWP::UserAgent;
my $url = url("http://" . $opt_H . $opt_u . $autostring);
my $req = new HTTP::Request 'GET', $url;
my $res = $ua->request($req);
#
# hopefully we´ve got something usefull
#
if ($res->is_success) {
    my ($accesses, $kbytes, $load, $uptime, $rps, $bps, $bpr, $busy, $idle, $performance, $score);
    $performance = "| ";
    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;  $performance .= "totalaccess=$accesses ";        next; }
        if (/^Total kBytes:\s+([0-9.]+)/)         { $kbytes   = $1;  $performance .= "totalkB=".$kbytes." ";          next; }
        if (/^CPULoad:\s+([0-9.]+)\s+/)           { $load     = $1;  $performance .= "CPUload=".$load." ";            next; }
        if (/^CPULoad:\s+[0-9.]+e/)               { $load     = 'E'; $performance .= "CPUload=E ";                    next; }
        if (/^Uptime:\s+([0-9.]+)\s+/)            { $uptime   = $1;  $performance .= "Uptime=$uptime ";               next; }
        if (/^ReqPerSec:\s+([0-9.]+)\s+/)         { $rps      = $1;  $performance .= "ReqPerSec=".$rps." ";           next; }
        if (/^ReqPerSec:\s+[0-9.]+e/)             { $rps      = 'E'; $performance .= "ReqPerSec=E ";                  next; }
        if (/^BytesPerSec:\s+([0-9.]+)\s+/)       { $bps      = $1;  $performance .= "kBytesPerSec=".($bps/1024)." "; next; }
        if (/^BytesPerSec:\s+[0-9.]+e/)           { $bps      = 'E'; $performance .= "kBytesPerSec=E ";               next; }
        if (/^BytesPerReq:\s+([0-9.]+)\s+/)       { $bpr      = $1;  $performance .= "kBytesPerReq=".($bpr/1024)." "; next; }
        if (/^ReqPerSec:\s+[0-9.]+e/)             { $bpr      = 'E'; $performance .= "kBytesPerReq=E ";               next; }
        if (/^BusyServers:\s+([0-9.]+)\s+/)       { $busy     = $1;  $performance .= "BusyServers=".$busy." ";        next; }
        if (/^BusyWorkers:\s+([0-9.]+)\s+/)       { $busy     = $1;  $performance .= "BusyServers=".$busy." ";        next; }
        if (/^IdleServers:\s+([0-9.]+)\s+/)       { $idle     = $1;  $performance .= "IdleServers=".$idle." ";        next; }
        if (/^IdleWorkers:\s+([0-9.]+)\s+/)       { $idle     = $1;  $performance .= "IdleServers=".$idle." ";        next; }
        if (/^Scoreboard:\s+([CSRWKDLG_.]+)\s+/)  { $score    = $1;                                                   next; }
        print "Unknown Status: $_\n";
    }
    #
    # now we even parse the whole scoreboard, just for fun
    #
    my %scores;
    $scores{'.'} = 0; # Unused
    $scores{'_'} = 0; # Waiting
    $scores{'S'} = 0; # Starting
    $scores{'R'} = 0; # Reading
    $scores{'W'} = 0; # Writing
    $scores{'K'} = 0; # Keepalive
    $scores{'D'} = 0; # DNS Lookup
    $scores{'L'} = 0; # Logging
    $scores{'G'} = 0; # Going
    $scores{'C'} = 0; # Closing
    foreach my $scorepoint (split //m, $score) { $scores{$scorepoint} += 1; }
    $performance .= "unused=$scores{'.'} wait=$scores{'_'} start=$scores{'S'} read=$scores{'R'} write=$scores{'W'} keepalive=$scores{'K'} dns=$scores{'D'} log=$scores{'L'} go=$scores{'G'} close=$scores{'C'}";
    #
    # compute return code
    #
    my $status = 'OK';
    $status = 'WARNING'  if($busy > $warn);
    $status = 'CRITICAL' if($busy > $alert);
    print "HTTPD $status: servers running $busy, idle $idle $performance\n";
    exit $ERRORS{$status};
} 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.
#
sub print_usage () {
    print "Usage: $0 [-hV] -H <host> -u <url> -w <warn> -c <crit>\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 " -c, --critical=INTEGER\n";
    print " performance level at which a critical message will be gererated.\n";
    print " -H, --hostname=ADDRESS\n";
    print " host name argument for server.\n";
    print " -h, --help\n";
    print " print detailed help screen.\n";
    print " -u, --url=PATH\n";
    print " location to call mod_status.\n";
    print " -V, --version\n";
    print " print version information.\n";
    print " -w, --warning=INTEGER\n";
    print " performance level at which a warning message will be gererated.\n";
    print "\n";
    print "\n";
}
#
# the end
#
