#!/usr/bin/env perl ###################################################################################################### # NEPP - Nagios External Perfdata Parser # This script is used as a wrapper to any Nagios plugin in order to seperatly collect and hand the # perf data off to an external application (like pnp4Nagios). # # Copyright (C) 2010 Frank Clements # # 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; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # # # Usage: # In order to use this simply run your Nagios checks via this wrapper in the command definitions. # Ex: $USER1$/neppc --local $USER1$/check_nrpe -H $HOSTADDRESS$ -c check_command -a # # The default mode is to spit out the performance data from the check to a file in /var/spool/nepp # which can then be processed by some external performance trending system. # # Why you ask? # At INetU we monitor more than 13,000 services and carry a requiremnt that all service checks # _must_ happen within a 5 minute window. Having Nagios process any performance data with this # many checks drops performance to about 500 checks/5 min. With performance processing turned off # in the nrpe.cfg performance climbs to > 10,000 checks 5 min on a single host. # # Having the trending data is required so the solution is to split it out and not ask Nagios to do # anything with it. # ###################################################################################################### use strict; use warnings; use Getopt::Long; #use Time::HiRes qw(time); ## Variable & Constant Definitions use constant VERSION => qw(0.1); use constant EXITSTATE => qw(OK WARNING CRITICAL UNKNOWN); my $optionLocal = undef; # Used for logging the perfdata on the local file system my $optionRemote = undef; # Used for logging the perfdata to a remote NEPP server (not yet implemented) my $optionCheckCommand = undef; # The check command we are wrapping my $optionCheckArgs = undef; # The check command's arguments my $optionSpool = undef; # The location of the local spool directory my $optionService = undef; # Performance results will be of type service my $optionHost = undef; # Performance results will be of type host my $optionVersion = undef; # Version display option my $optionHelp = undef; # Help display option my $optionCommand = undef; # The command and arguments to wrap - Needs to be quoted on the cli my $perfType = qw(service); # Default type is service ## Subroutines # Show version sub displayVersion{print "Version: " . VERSION; exit 0}; # Display detailed help information sub displayHelp{ displayUsage(); print <] [--service|--host] [--help] [--version] --command=\" \"\n"; } # Process the command line arguments sub processOptions { Getopt::Long::Configure ("bundling"); GetOptions( 'local' => \$optionLocal, 'spool:s' => \$optionSpool, 'host' => \$optionHost, 'service' => \$optionService, 'command:s' => \$optionCommand, 'version' => \$optionVersion, 'help' => \$optionHelp ); displayVersion() if $optionVersion; # Display version info displayHelp() if $optionHelp || ! $optionCommand; # Display help # Set te default spool directory if not specified on the cli $optionSpool = defined $optionSpool ? $optionSpool : qw(/var/spool/nepp); $perfType = qw(host) if( $optionHost ); } # Create the data to be stuffed into the perfdata file sub createPerfdataOutput { my $commandOutput = shift; my $exitCode = shift; # Split the command output and the perfdata my ($output, $perfdata) = split(/\|/, $commandOutput); chomp($output); chomp($perfdata) if($perfdata); print $output; if( $perfType eq 'service' && $perfdata ) { my $servicePerfdata = "DATATYPE::SERVICEPERFDATA\tTIMET::".$ENV{'NAGIOS_TIMET'}."\tHOSTNAME::".$ENV{'NAGIOS_HOSTNAME'}."\tSERVICEDESC::".$ENV{'NAGIOS_SERVICEDESC'}."\tSERVICEPERFDATA::".$perfdata."\tSERVICECHECKCOMMAND::".$ENV{'NAGIOS_SERVICECHECKCOMMAND'}."\tHOSTSTATE::".$ENV{'NAGIOS_HOSTSTATE'}."\tHOSTSTATETYPE::".$ENV{'NAGIOS_HOSTSTATETYPE'}."\tSERVICESTATE::".(EXITSTATE)[$exitCode]."\tSERVICESTATETYPE::".$ENV{'NAGIOS_SERVICESTATETYPE'}."\tSERVICEOUTPUT::".$output."\n"; return $servicePerfdata; } return 0; # 1 evaluates to true which is not what we want if we get here. } # Write out the performance data file sub writeFile { my $template = shift; my $fileName = $optionSpool."/".$perfType."-perfdata.".time(); # Check if the file already exists - if it does append to it, otherwise create it if( -f $fileName ) { open(FILE, '>>', $fileName) || die("Unable to open $fileName: $!\n"); } else { open(FILE, '>', $fileName) || die("Unable to open $fileName: $!\n"); } print FILE $template; close(FILE); } ## Main Section of tool processOptions(); # Process command line arguments my $result = `$optionCommand`; # Run and store the command output my $ecode = $?>>8; # Store the exit status from the command # Check the exit status right away for UNKNOWN conditions if( $ecode == 4 ) { print $result; exit $ecode; } my $perfData = createPerfdataOutput($result, $ecode); writeFile($perfData) if($perfData); exit $ecode; # Always leave with the exit status. ## # TODO: # # * Create a daemon which can accept bulk updates from multiple outside nepp clients so that something # like NFS or scp does not have to bused to aggregate the data.