From 870f13fdb548a59ec1cc0d84ac634673598239ae Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Sun, 11 May 2008 18:36:48 -0400 Subject: Add custom_query action. --- check_postgres.pl | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 6 deletions(-) (limited to 'check_postgres.pl') diff --git a/check_postgres.pl b/check_postgres.pl index 91a46ea7f..efacda202 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -28,7 +28,7 @@ $Data::Dumper::Varname = 'POSTGRES'; $Data::Dumper::Indent = 2; $Data::Dumper::Useqq = 1; -our $VERSION = '1.5.2'; +our $VERSION = '1.6.0'; use vars qw/ %opt $PSQL $res $COM $SQL $db /; @@ -104,8 +104,10 @@ die $USAGE unless 'dbpass=s@', 'PSQL=s', - 'logfile=s', ## used by check_logfile only + 'logfile=s', ## used by check_logfile only 'queryname=s', ## used by query_runtime only + 'query=s', ## used by custom_query only + 'checktype=s', ## used by custom_query only ) and keys %opt and ! @ARGV; @@ -150,6 +152,7 @@ my $action_info = { backends => [1, 'Number of connections, compared to max_connections.'], bloat => [0, 'Check for table and index bloat.'], connection => [0, 'Simple connection check.'], + custom_query => [0, 'Run a custom query.'], database_size => [0, 'Report if a database is too big.'], disk_space => [1, 'Checks space of local disks Postgres is using.'], index_size => [0, 'Checks the size of indexes only.'], @@ -502,7 +505,6 @@ elsif ($opt{excludeuser}) { } } - ## Check number of connections, compare to max_connections check_backends() if $action eq 'backends'; @@ -571,6 +573,9 @@ check_txn_time() if $action eq 'txn_time'; ## Check the maximum age of idle in transaction connections check_txn_idle() if $action eq 'txn_idle'; +## Run a custom query +check_custom_query() if $action eq 'custom_query'; + finishup(); exit; @@ -646,7 +651,7 @@ sub run_command { ## "regex" - the query must match this or we throw an error ## "emptyok" - it's okay to not match any rows at all - my $string = shift; + my $string = shift || ''; my $arg = shift || {}; my $info = { command => $string, db => [], hosts => 0 }; @@ -960,7 +965,10 @@ sub validate_range { my $critical = exists $opt{critical} ? $opt{critical} : exists $opt{warning} ? '' : $arg->{default_critical} || ''; - if ('seconds' eq $type) { + if ('string' eq $type) { + ## Don't use this unless you have to + } + elsif ('seconds' eq $type) { if (length $warning) { if ($warning !~ $timesecre) { ndie qq{Invalid argument to 'warning' option: must be number of seconds\n}; @@ -2502,6 +2510,63 @@ sub check_version { } ## end of check_version +sub check_custom_query { + + ## Run a user-supplied query, then parse the results + ## If you end up using this to make a useful query, consider making it + ## into a specific action and sending in a patch! + ## Checktype must be one of: string, time, size, integer + + my $valtype = $opt{checktype} || 'integer'; + + my ($warning, $critical) = validate_range({type => $valtype, leastone => 1}); + + my $query = $opt{query} or ndie q{Must provide a query string}; + + my $info = run_command($query); + + for $db (@{$info->{db}}) { + + chomp $db->{slurp}; + if (! length $db->{slurp}) { + add_unknown "No rows returned"; + next; + } + + while ($db->{slurp} =~ /(\S+)\s+\|\s+(.+)$/gm) { + my ($data, $msg) = ($1,$2); + $db->{perf} .= " $msg"; + my $gotmatch = 0; + if (length $critical) { + if (($valtype eq 'string' and $data eq $critical) + or + ($data >= $critical)) { ## covers integer, time, size + add_critical "$data"; + $gotmatch = 1; + } + } + + if (length $warning and ! $gotmatch) { + if (($valtype eq 'string' and $data eq $warning) + or + ($data >= $warning)) { + add_warning "$data"; + $gotmatch = 1; + } + } + + if (! $gotmatch) { + add_ok "$data"; + } + + } ## end each row returned + } + + return; + +} ## end of check_custom_query + + __END__ @@ -2513,7 +2578,7 @@ check_postgres.pl - Postgres monitoring script for Nagios =head1 VERSION -This documents describes B version 1.5.2 +This documents describes B version 1.6.0 =head1 SYNOPSIS @@ -2783,6 +2848,46 @@ Example 2: Give a critical if table 'orders' on host 'sami' has more than 10 meg Simply connects, issues a 'SELECT version()', and leaves. Takes no B<--warning> or B<--critical> options. +=item B (symlink: check_postgres_custom_query) + +Runs a custom query of your choosing, and parses the results. The query itself is passed in through +the C argument, and should be kept as simple as possible. If at all possible, wrap it in +a view of function to keep things easier to manage. The query should return exactly two columns: the first +is the result that will be checked, and the second is any performance data you want sent. At least one +of warning or critical must be set. What they are set to depends on the type of query you are running. +There are four types of custom_queries that can be run, specified by the C argument. If none +is specified, this action defaults to 'integer'. The four types are: + +B: +Does a simple integer comparison. The first column should be a simple integer, and the warning and +critical values should be the same. + +B: +The warning and critical are strings, and are triggered only if the value in the first column matches +it exactly. This is case-sensitive. + +B