From 2171614181652456b17cbb8debd3b45bc817d95e Mon Sep 17 00:00:00 2001 From: Jan Wagner Date: Mon, 18 Nov 2013 16:39:57 +0100 Subject: [PATCH] Add check_tomcat --- check_tomcat/Makefile | 3 + check_tomcat/check_tomcat | 387 ++++++++++++++++++++++++++++++++++ check_tomcat/check_tomcat.cfg | 5 + check_tomcat/control | 6 + check_tomcat/copyright | 7 + 5 files changed, 408 insertions(+) create mode 100644 check_tomcat/Makefile create mode 100644 check_tomcat/check_tomcat create mode 100644 check_tomcat/check_tomcat.cfg create mode 100644 check_tomcat/control create mode 100644 check_tomcat/copyright diff --git a/check_tomcat/Makefile b/check_tomcat/Makefile new file mode 100644 index 0000000..cf9673d --- /dev/null +++ b/check_tomcat/Makefile @@ -0,0 +1,3 @@ +#/usr/bin/make -f + +include ../common.mk diff --git a/check_tomcat/check_tomcat b/check_tomcat/check_tomcat new file mode 100644 index 0000000..d67cbec --- /dev/null +++ b/check_tomcat/check_tomcat @@ -0,0 +1,387 @@ +#!/usr/bin/perl + +############################################################################# +# # +# This script was initially developed by Lonely Planet for internal use # +# and has kindly been made available to the Open Source community for # +# redistribution and further development under the terms of the # +# GNU General Public License v3: http://www.gnu.org/licenses/gpl.html # +# # +############################################################################# +# # +# This script is supplied 'as-is', in the hope that it will be useful, but # +# neither Lonely Planet nor the authors make any warranties or guarantees # +# as to its correct operation, including its intended function. # +# # +# Or in other words: # +# Test it yourself, and make sure it works for YOU. # +# # +############################################################################# +# Author: George Hansper e-mail: george@hansper.id.au # +############################################################################# + +use strict; +use LWP; +use LWP::UserAgent; +use Getopt::Std; +use XML::XPath; + +my %optarg; +my $getopt_result; + +my $lwp_user_agent; +my $http_request; +my $http_response; +my $url; +my $body; + +my @message; +my @message_perf; +my $exit = 0; +my @exit = qw/OK: WARNING: CRITICAL:/; + +my $rcs_id = '$Id: check_tomcat.pl,v 1.4 2013/03/15 10:45:41 george Exp $'; +my $rcslog = ' + $Log: check_tomcat.pl,v $ + Revision 1.4 2013/03/15 10:45:41 george + Fixed bug in % threads thresholds, which appear if multiple connectors are in use (thanks to Andreas Lamprecht for reporting this). + Changed MB to MiB in output text. + + Revision 1.3 2011/12/11 04:56:27 george + Added currentThreadCount to performance data. + + Revision 1.2 2011/11/18 11:30:57 george + Added capability to extract the connector names, and check any or all tomcat connectors for sufficient free threads. + Stripped quotes from connector names to work around tomcat7 quirkiness. + + Revision 1.1 2011/04/16 12:05:26 george + Initial revision + + '; + +# Defaults... +my $timeout = 10; # Default timeout +my $host = 'localhost'; # default host header +my $host_ip = 'localhost'; # default IP +my $port = 80; # default port +my $user = 'nagios'; # default user +my $password = 'nagios'; # default password +my $uri = '/manager/status?XML=true'; #default URI +my $http = 'http'; +my $connector_arg = undef; +my $opt_warn_threads = "25%"; +my $opt_crit_threads = "10%"; +my $warn_threads; +my $crit_threads; +# Memory thresholds are tight, because garbage collection kicks in only when memory is low anyway +my $opt_warn_memory = "5%"; +my $opt_crit_memory = "2%"; +my $warn_memory; +my $crit_memory; + +my $xpath; +my %xpath_checks = ( + maxThreads => '/status/connector/threadInfo/@maxThreads', + currentThreadCount => '/status/connector/threadInfo/@currentThreadCount', + currentThreadsBusy => '/status/connector/threadInfo/@currentThreadsBusy', + memMax => '/status/jvm/memory/@max', + memFree => '/status/jvm/memory/@free', + memTotal => '/status/jvm/memory/@total', +); +# XPath examples... +# /status/jvm/memory/@free +# /status/connector[attribute::name="http-8080"]/threadInfo/@maxThreads +# /status/connector/threadInfo/@* <- returns multiple nodes + +my %xpath_check_results; + +sub VERSION_MESSAGE() { + print "$^X\n$rcs_id\n"; +} + +sub HELP_MESSAGE() { + print <new; +$lwp_user_agent->timeout($timeout); +if ( $port == 80 || $port == 443 || $port eq "" ) { + $lwp_user_agent->default_header('Host' => $host); +} else { + $lwp_user_agent->default_header('Host' => "$host:$port"); +} + +$url = "$http://${host_ip}:${port}$uri"; +$http_request = HTTP::Request->new(GET => $url); + +printv "--------------- GET $url"; +printv $lwp_user_agent->default_headers->as_string . $http_request->headers_as_string; + +$http_response = $lwp_user_agent->request($http_request); +printv "---------------\n" . $http_response->protocol . " " . $http_response->status_line; +printv $http_response->headers_as_string; +printv "Content has " . length($http_response->content) . " bytes \n"; + +if ($http_response->is_success) { + $body = $http_response->content; + my $xpath = XML::XPath->new( xml => $body ); + my $xpath_check; + # Parse the data out of the XML... + foreach $xpath_check ( keys %xpath_checks ) { + #print keys(%{$xpath_check}) , "\n"; + my $path = $xpath_checks{$xpath_check}; + $path =~ s{\$port}{$port}; + #print $xpath_check->{xpath} , "\n"; + my $nodeset = $xpath->find($path); + if ( $nodeset->get_nodelist == 0 ) { + push @message, "$path not found"; + $exit |= 2; + push @message_perf, "$path=not_found"; + next; + } + foreach my $node ($nodeset->get_nodelist) { + my $connector_name = $node->getParentNode()->getParentNode()->getAttribute("name"); + $connector_name =~ s/^["'\s]+//; + $connector_name =~ s/["'\s]+$//; + my $value = $node->string_value(); + if ( $value =~ /^"?([0-9.]+)"?$/ ) { + $value = $1; + } else { + push @message, "$path is not numeric"; + $exit |= 2; + push @message_perf, "$path=not_numeric"; + next; + } + if ( $xpath_check =~ /^mem/ ) { + # This is the .../memory/.. xpath, just store the value in the hash + $xpath_check_results{$xpath_check} = $value; + } elsif ( $connector_name =~ /${connector_arg}/ && $connector_name ne "" ) { + # This is a .../threadInfo/... xpath, put the result into a hash (key is connector_name) + $xpath_check_results{$xpath_check}{$connector_name} = $value; + } + } + } + # Now apply the logic and check the results + #---------------------------------------------- + # Check memory + #---------------------------------------------- + my $jvm_mem_available = $xpath_check_results{memFree} + $xpath_check_results{memMax} - $xpath_check_results{memTotal}; + printv(sprintf("free=%d max=%d total=%d",$xpath_check_results{memFree}/1024, $xpath_check_results{memMax}/1024, $xpath_check_results{memTotal}/1024)); + if ( $opt_warn_memory =~ /(.*)%$/ ) { + $warn_memory = int($1 * $xpath_check_results{memMax} / 100); + } else { + # Convert to bytes + $warn_memory =int($opt_warn_memory * 1024 * 1024); + } + printv("warning at $warn_memory bytes (". ( $warn_memory / 1024 /1024 )."MiB) free, max=$xpath_check_results{memMax}"); + + if ( $opt_crit_memory =~ /(.*)%$/ ) { + $crit_memory = int($1 * $xpath_check_results{memMax} / 100); + } else { + # Convert to bytes + $crit_memory = int($opt_crit_memory * 1024 * 1024); + } + printv("critical at $crit_memory bytes (". ( $crit_memory / 1024 /1024 )."MiB) free, max=$xpath_check_results{memMax}"); + + if ( $jvm_mem_available <= $crit_memory ) { + $exit |= 2; + push @message, sprintf("Memory critical <%d MiB,",$crit_memory/1024/1024); + } elsif ( $jvm_mem_available <= $warn_memory ) { + $exit |= 1; + push @message, sprintf("Memory low <%d MiB,",$warn_memory/1024/1024); + } + push @message, sprintf("memory in use %d MiB (%d MiB);", + ( $xpath_check_results{memMax} - $jvm_mem_available ) / ( 1024 * 1024), + $xpath_check_results{memMax} / ( 1024 * 1024) + ); + push @message_perf, "used=".( $xpath_check_results{memMax} - $jvm_mem_available ) . " free=$jvm_mem_available max=$xpath_check_results{memMax}"; + + #---------------------------------------------- + # Check threads + #---------------------------------------------- + my $name; + foreach $name ( keys( %{$xpath_check_results{currentThreadsBusy}} ) ) { + + if ( $opt_warn_threads =~ /(.*)%$/ ) { + $warn_threads = int($1 * $xpath_check_results{maxThreads}{$name} / 100); + } else { + $warn_threads = $opt_warn_threads; + } + printv("warning at $warn_threads threads free, max=$xpath_check_results{maxThreads}{$name}"); + + if ( $opt_crit_threads =~ /(.*)%$/ ) { + $crit_threads = int($1 * $xpath_check_results{maxThreads}{$name} / 100); + } else { + $crit_threads = $opt_crit_threads; + } + printv("critical at $crit_threads threads free, max=$xpath_check_results{maxThreads}{$name}"); + + my $threads_available = $xpath_check_results{maxThreads}{$name} - $xpath_check_results{currentThreadsBusy}{$name}; + if ( $threads_available <= $crit_threads ) { + $exit |= 2; + push @message, sprintf("Critical: free_threads<%d",$crit_threads); + } elsif ( $threads_available <= $warn_threads ) { + $exit |= 1; + push @message, sprintf("Warning: free_threads<%d",$warn_threads); + } + push @message, sprintf("threads[$name]=%d(%d);", + $xpath_check_results{currentThreadsBusy}{$name}, + $xpath_check_results{maxThreads}{$name} + ); + if ( defined($optarg{n}) ) { + push @message_perf, "currentThreadsBusy[$name]=$xpath_check_results{currentThreadsBusy}{$name} currentThreadCount[$name]=$xpath_check_results{currentThreadCount}{$name} maxThreads[$name]=$xpath_check_results{maxThreads}{$name}"; + } else { + # For the sake of backwards-compatability of graphs etc... + push @message_perf, "currentThreadsBusy=$xpath_check_results{currentThreadsBusy}{$name} currentThreadCount=$xpath_check_results{currentThreadCount}{$name} maxThreads=$xpath_check_results{maxThreads}{$name}"; + } + } + if ( keys(%{$xpath_check_results{currentThreadsBusy}}) == 0 ) { + # no matching connectors found - this is not OK. + $exit |= 1; + push @message, "Warning: No tomcat connectors matched name =~ /$connector_arg/"; + } +} elsif ( $http_response->code == 401 ) { + print "WARNING: $url " . $http_response->protocol . " " . $http_response->status_line ."\n"; + exit 1; +} else { + print "CRITICAL: $url " . $http_response->protocol . " " . $http_response->status_line ."\n"; + exit 2; +} + +if ( $exit == 3 ) { + $exit = 2; +} + +print "$exit[$exit] ". join(" ",@message) . "|". join(" ",@message_perf) . "\n"; +exit $exit; diff --git a/check_tomcat/check_tomcat.cfg b/check_tomcat/check_tomcat.cfg new file mode 100644 index 0000000..4c8cdc4 --- /dev/null +++ b/check_tomcat/check_tomcat.cfg @@ -0,0 +1,5 @@ +# 'check_tomcat_status' command definition +define command{ + command_name check_tomcat_status + command_line /usr/lib/monitoring-plugins/check_tomcat -H $HOSTADDRESS$ -l $ARG1$ -a $ARG2$ $ARG3$ + } diff --git a/check_tomcat/control b/check_tomcat/control new file mode 100644 index 0000000..5746571 --- /dev/null +++ b/check_tomcat/control @@ -0,0 +1,6 @@ +Homepage: https://www.monitoringexchange.org/inventory/Check-Plugins/Software/Java/check_tomcat-pl +Watch: https://www.monitoringexchange.org/attachment/preview/Check-Plugins/Software/Java/check_tomcat-pl/13-03-15_12-09-48_check_tomcat.pl Id: check_tomcat.pl,v ([0-9.]+) +Uploaders: Jan Wagner +Description: plugin to check the tomcat status page. +Recommends: libwww-perl, libxml-xpath-perl +Version: 1.4 diff --git a/check_tomcat/copyright b/check_tomcat/copyright new file mode 100644 index 0000000..a7ec1d8 --- /dev/null +++ b/check_tomcat/copyright @@ -0,0 +1,7 @@ +Copyright (c) George Hansper + +License: GPL v3 + + On Debian systems, the complete text of the GNU General + Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". +