From dc683e6fd710219988737a92c62eeccf2b743296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Mon, 7 Nov 2011 20:51:15 +0800 Subject: [PATCH 01/42] Add a check cluster_id This check is responsible to confirm that the Database System Identifier found by pg_controldata is the one expected. warning and critical allowed (like check_postgres_checksum) and must be run on PostgreSQL server (like check_postgres_checkpoint) While here, I created a new function open_controldata which can be used in other places where pg_controldata is used. --- check_postgres.pl | 128 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 2 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index 622c5d43..101550dc 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -99,6 +99,9 @@ package check_postgres; 'bloat-nomin' => q{no relations meet the minimum bloat criteria}, 'bloat-table' => q{(db $1) table $2.$3 rows:$4 pages:$5 shouldbe:$6 ($7X) wasted size:$8 ($9)}, 'bug-report' => q{Please report these details to check_postgres@bucardo.org:}, + 'checkcluster-id' => q{Database system identifier:}, + 'checkcluster-msg' => q{cluster_id: $1}, + 'checkcluster-nomrtg'=> q{Must provide a number via the --mrtg option}, 'checkmode-state' => q{Database cluster state:}, 'checkmode-recovery' => q{in archive recovery}, 'checkpoint-baddir' => q{Invalid data_directory: "$1"}, @@ -108,7 +111,7 @@ package check_postgres; 'checkpoint-nodir' => q{Must supply a --datadir argument or set the PGDATA environment variable}, 'checkpoint-nodp' => q{Must install the Perl module Date::Parse to use the checkpoint action}, 'checkpoint-noparse' => q{Unable to parse pg_controldata output: "$1"}, - 'checkpoint-noregex' => q{Call to pg_controldata $1 failed}, + 'checkpoint-noregex' => q{Unable to find the regex for this check}, 'checkpoint-nosys' => q{Could not call pg_controldata: $1}, 'checkpoint-ok' => q{Last checkpoint was 1 second ago}, 'checkpoint-ok2' => q{Last checkpoint was $1 seconds ago}, @@ -353,7 +356,7 @@ package check_postgres; 'checkpoint-nodir' => q{Vous devez fournir un argument --datadir ou configurer la variable d'environnement PGDATA}, 'checkpoint-nodp' => q{Vous devez installer le module Perl Date::Parse pour utiliser l'action checkpoint}, 'checkpoint-noparse' => q{Incapable d'analyser le résultat de la commande pg_controldata : "$1"}, - 'checkpoint-noregex' => q{Échec de l'appel à pg_controldata $1}, + 'checkpoint-noregex' => q{La regex pour ce test n'a pas été trouvée}, 'checkpoint-nosys' => q{N'a pas pu appeler pg_controldata : $1}, 'checkpoint-ok' => q{Le dernier CHECKPOINT est survenu il y a une seconde}, 'checkpoint-ok2' => q{Le dernier CHECKPOINT est survenu il y a $1 secondes}, @@ -1112,6 +1115,7 @@ package check_postgres; backends => [1, 'Number of connections, compared to max_connections.'], bloat => [0, 'Check for table and index bloat.'], checkpoint => [1, 'Checks how long since the last checkpoint'], + cluster_id => [1, 'Checks the Database System Identifier'], commitratio => [0, 'Report if the commit ratio of a database is too low.'], connection => [0, 'Simple connection check.'], custom_query => [0, 'Run a custom query.'], @@ -1919,6 +1923,9 @@ sub finishup { ## Check how long since the last checkpoint check_checkpoint() if $action eq 'checkpoint'; +## Check the Datasbae System Identifier +check_cluster_id() if $action eq 'cluster_id'; + ## Check for disabled triggers check_disabled_triggers() if $action eq 'disabled_triggers'; @@ -3114,6 +3121,50 @@ sub perfname { } ## end of perfname; +sub open_controldata { + ## Requires $ENV{PGDATA} or --datadir + + ## Find the data directory, make sure it exists + my $dir = $opt{datadir} || $ENV{PGDATA}; + + if (!defined $dir or ! length $dir) { + ndie msg('checkpoint-nodir'); + } + + if (! -d $dir) { + ndie msg('checkpoint-baddir', $dir); + } + + ## Run pg_controldata + my $pgc + = $ENV{PGCONTROLDATA} ? $ENV{PGCONTROLDATA} + : $ENV{PGBINDIR} ? "$ENV{PGBINDIR}/pg_controldata" + : 'pg_controldata'; + $COM = qq{$pgc "$dir"}; + eval { + $res = qx{$COM 2>&1}; + }; + if ($@) { + ndie msg('checkpoint-nosys', $@); + } + + ## If the path is echoed back, we most likely have an invalid data dir + if ($res =~ /$dir/) { + ndie msg('checkpoint-baddir2', $dir); + } + + if ($res =~ /WARNING: Calculated CRC checksum/) { + ndie msg('checkpoint-badver', $dir); + } + if ($res !~ /^pg_control.+\d+/) { + ndie msg('checkpoint-badver2'); + } + + ## return the pg_controldata output + return $res; +} + + sub check_archive_ready { ## Check on the number of WAL archive with status "ready" @@ -3743,6 +3794,58 @@ sub check_checkpoint { } ## end of check_checkpoint +sub check_cluster_id { + + + ## Verify the Database System Identifier provided by pg_controldata + ## Supports: Nagios, MRTG + ## One of warning or critical must be given (but not both) + ## It should run one time to find out the expected cluster-id + ## You can use --critical="0" to find out the current cluster-id + ## You can include or exclude settings as well + ## Example: + ## check_postgres_cluster_id --critical="5633695740047915125" + + my ($warning, $critical) = validate_range({type => 'integer', onlyone => 1}); + + $db->{host} = ''; + + ## Run pg_controldata, grab the cluster-id + $res = open_controldata(); + + my $regex = msg('checkcluster-id'); + if ($res !~ /$regex\s*(.+)/) { ## no critic (ProhibitUnusedCapture) + ## Just in case, check the English one as well + $regex = msg_en('checkcluster-id'); + if ($res !~ /$regex\s*(.+)/) { + ndie msg('checkpoint-noregex'); + } + } + my $ident = $1; + + my $msg = msg('checkcluster-msg', $ident); + if ($MRTG) { + $opt{mrtg} or ndie msg('checksum-nomrtg'); + do_mrtg({one => $opt{mrtg} eq $ident ? 1 : 0, msg => $ident}); + } + if ($critical and $critical ne $ident) { + add_critical $msg; + } + elsif ($warning and $warning ne $ident) { + add_warning $msg; + } + elsif (!$critical and !$warning) { + add_unknown $msg; + } + else { + add_ok $msg; + } + + return; + +} ## end of check_cluster_id + + sub check_commitratio { ## Check the commitratio of one or more databases @@ -8091,6 +8194,27 @@ =head2 B For MRTG or simple output, returns the number of seconds. +=head2 B + +(C) Checks that the Database System Identifier +provided by pg_controldata is the same as last time you checked. This must run on the same +server as the database that is being checked (e.g. the -h flag will not work). +Either the I<--warning> or the I<--critical> option should be given, but not both. The value +of each one is the cluster identifier, an integer value. You can run with the special C<--critical=0> option +to find out an existing cluster identifier. + +Example 1: Find the initial identifier + + check_postgres_cluster_id --critical=0 --datadir=/var//lib/postgresql/9.0/main + +Example 2: Make sure the cluster is the same and warn if not, using the result from above. + + check_postgres_cluster_id --critical=5633695740047915135 + +For MRTG output, returns a 1 or 0 indicating success of failure of the identifier to match. A +identifier must be provided as the C<--mrtg> argument. The fourth line always gives the +current identifier. + =head2 B (C) Checks the commit ratio of all databases and complains when they are too low. From 39523cb6dfeea023fb7e17a558ce0d46c0033220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Mon, 7 Nov 2011 20:57:19 +0800 Subject: [PATCH 02/42] Reduce code duplicates around pg_controldata Use the open_controldata where pg_controldata was used previously. Also split the code for make_sure_standby_mode to reduce code for the future option make_sure_prod. --- check_postgres.pl | 91 ++++++++++------------------------------------- 1 file changed, 18 insertions(+), 73 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index 101550dc..3b5537e3 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -1521,59 +1521,37 @@ sub do_mrtg_stats { do_mrtg({one => $one, two => $two, msg => $msg}); } -sub make_sure_standby_mode { +sub make_sure_mode_is { - ## Checks if database in standby mode ## Requires $ENV{PGDATA} or --datadir - ## Find the data directory, make sure it exists - my $dir = $opt{datadir} || $ENV{PGDATA}; - - if (!defined $dir or ! length $dir) { - ndie msg('checkpoint-nodir'); - } - - if (! -d $dir) { - ndie msg('checkpoint-baddir', $dir); - } - $db->{host} = ''; ## Run pg_controldata, grab the mode - my $pgc - = $ENV{PGCONTROLDATA} ? $ENV{PGCONTROLDATA} - : $ENV{PGBINDIR} ? "$ENV{PGBINDIR}/pg_controldata" - : 'pg_controldata'; - $COM = qq{$pgc "$dir"}; - eval { - $res = qx{$COM 2>&1}; - }; - if ($@) { - ndie msg('checkpoint-nosys', $@); - } - - ## If the path is echoed back, we most likely have an invalid data dir - if ($res =~ /$dir/) { - ndie msg('checkpoint-baddir2', $dir); - } - - if ($res =~ /WARNING: Calculated CRC checksum/) { - ndie msg('checkpoint-badver', $dir); - } - if ($res !~ /^pg_control.+\d+/) { - ndie msg('checkpoint-badver2'); - } + $res = open_controldata(); my $regex = msg('checkmode-state'); if ($res !~ /$regex\s*(.+)/) { ## no critic (ProhibitUnusedCapture) ## Just in case, check the English one as well $regex = msg_en('checkmode-state'); if ($res !~ /$regex\s*(.+)/) { - ndie msg('checkpoint-noregex', $dir); + ndie msg('checkpoint-noregex'); } } my $last = $1; - $regex = msg('checkmode-recovery'); + + return $last; + +} + +sub make_sure_standby_mode { + + ## Checks if database in standby mode + ## Requires $ENV{PGDATA} or --datadir + + my $last = make_sure_mode_is(); + + my $regex = msg('checkmode-recovery'); if ($last =~ /$regex/) { $STANDBY = 1; } @@ -3708,50 +3686,17 @@ sub check_checkpoint { forcemrtg => 1, }); - ## Find the data directory, make sure it exists - my $dir = $opt{datadir} || $ENV{PGDATA}; - - if (!defined $dir or ! length $dir) { - ndie msg('checkpoint-nodir'); - } - - if (! -d $dir) { - ndie msg('checkpoint-baddir', $dir); - } - $db->{host} = ''; ## Run pg_controldata, grab the time - my $pgc - = $ENV{PGCONTROLDATA} ? $ENV{PGCONTROLDATA} - : $ENV{PGBINDIR} ? "$ENV{PGBINDIR}/pg_controldata" - : 'pg_controldata'; - $COM = qq{$pgc "$dir"}; - eval { - $res = qx{$COM 2>&1}; - }; - if ($@) { - ndie msg('checkpoint-nosys', $@); - } - - ## If the path is echoed back, we most likely have an invalid data dir - if ($res =~ /$dir/) { - ndie msg('checkpoint-baddir2', $dir); - } - - if ($res =~ /WARNING: Calculated CRC checksum/) { - ndie msg('checkpoint-badver', $pgc); - } - if ($res !~ /^pg_control.+\d+/) { - ndie msg('checkpoint-badver2'); - } + $res = open_controldata(); my $regex = msg('checkpoint-po'); if ($res !~ /$regex\s*(.+)/) { ## no critic (ProhibitUnusedCapture) ## Just in case, check the English one as well $regex = msg_en('checkpoint-po'); if ($res !~ /$regex\s*(.+)/) { - ndie msg('checkpoint-noregex', $dir); + ndie msg('checkpoint-noregex'); } } my $last = $1; From 63fe159796f5d2c9e01b39f97fe09fd1878fdf6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Mon, 7 Nov 2011 21:00:02 +0800 Subject: [PATCH 03/42] Add an --assume-prod option This is based on --assume-standby-mode. Reduce the option name per suggestion from Greg (but I kept the original one for standby mode). The option is only used in check_postgres_checkpoint and allows to confirm or emit a critical if the server is not in the expected mode. Note: this can be used in other places, and maybe improved (to reduce the number og open_controldata calls) TODO/FIXME: * I found that --assume-p or --assume-s are viewed by GetOpt like the longer version of the option, a bug ? * The original code to call pg_controldata does not work in French (because of regex/locale). Why not use LANG=C in those checks where there is NO point to use locale and error prone regex ? --- check_postgres.pl | 63 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index 3b5537e3..c5e5d303 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -104,6 +104,7 @@ package check_postgres; 'checkcluster-nomrtg'=> q{Must provide a number via the --mrtg option}, 'checkmode-state' => q{Database cluster state:}, 'checkmode-recovery' => q{in archive recovery}, + 'checkmode-prod' => q{in production}, 'checkpoint-baddir' => q{Invalid data_directory: "$1"}, 'checkpoint-baddir2' => q{pg_controldata could not read the given data directory: "$1"}, 'checkpoint-badver' => q{Failed to run pg_controldata - probably the wrong version ($1)}, @@ -163,6 +164,7 @@ package check_postgres; 'logfile-stderr' => q{Logfile output has been redirected to stderr: please provide a filename}, 'logfile-syslog' => q{Database is using syslog, please specify path with --logfile option (fac=$1)}, 'mode-standby' => q{Server in standby mode}, + 'mode' => q{mode}, 'mrtg-fail' => q{Action $1 failed: $2}, 'new-ver-nocver' => q{Could not download version information for $1}, 'new-ver-badver' => q{Could not parse version information for $1}, @@ -934,6 +936,7 @@ package check_postgres; 'debugoutput=s', 'no-check_postgresrc', 'assume-standby-mode', + 'assume-prod', 'action=s', 'warning=s', @@ -1206,6 +1209,7 @@ package check_postgres; Other options: --assume-standby-mode assume that server in continious WAL recovery mode + --assume-prod assume that server in production mode --PSQL=FILE location of the psql executable; avoid using if possible -v, --verbose verbosity level; can be used more than once to increase the level -h, --help display this help information @@ -1252,7 +1256,9 @@ package check_postgres; ## Check the current database mode our $STANDBY = 0; +our $MASTER = 0; make_sure_standby_mode() if $opt{'assume-standby-mode'}; +make_sure_prod() if $opt{'assume-prod'}; ## We don't (usually) want to die, but want a graceful Nagios-like exit instead sub ndie { @@ -1560,6 +1566,21 @@ sub make_sure_standby_mode { } ## end of make_sure_standby_mode +sub make_sure_prod { + + ## Checks if database in production mode + ## Requires $ENV{PGDATA} or --datadir + + my $last = make_sure_mode_is(); + + my $regex = msg('checkmode-prod'); + if ($last =~ /$regex/) { + $MASTER = 1; + } + + return; + +} ## end of make_sure_production_mode sub finishup { @@ -3661,7 +3682,6 @@ sub check_bloat { } ## end of check_bloat - sub check_checkpoint { ## Checks how long in seconds since the last checkpoint on a WAL slave @@ -3674,6 +3694,9 @@ sub check_checkpoint { ## may make more sense on the master, or we may want to look at ## the WAL segments received/processed instead of the checkpoint ## timestamp. + ## This checks can use the optionnal --asume-standby-mode or + ## --assume-prod: if the mode found is not the mode assumed, a + ## CRITICAL is emitted. ## Supports: Nagios, MRTG ## Warning and critical are seconds @@ -3718,11 +3741,35 @@ sub check_checkpoint { $db->{perf} = sprintf '%s=%s;%s;%s', perfname(msg('age')), $diff, $warning, $critical; + my $mode = ''; + if ($STANDBY) { + $mode = 'STANDBY'; + } + if ($MASTER) { + $mode = 'MASTER'; + } + + ## If we have an assume flag, then honor it. + my $goodmode = 1; + if ($opt{'assume-standby-mode'} and not $STANDBY) { + $goodmode = 0; + $mode = 'NOT STANDBY'; + } + elsif ($opt{'assume-prod'} and not $MASTER) { + $goodmode = 0; + $mode = 'NOT MASTER'; + } + + if (length($mode) > 0) { + $db->{perf} .= sprintf ' %s=%s', + perfname(msg('mode')), $mode; + } + if ($MRTG) { do_mrtg({one => $diff, msg => $msg}); } - if (length $critical and $diff >= $critical) { + if ((length $critical and $diff >= $critical) or not $goodmode) { add_critical $msg; return; } @@ -7862,6 +7909,16 @@ =head1 OTHER OPTIONS postgres@db$./check_postgres.pl --action=version --warning=8.1 --datadir /var/lib/postgresql/8.3/main/ --assume-standby-mode POSTGRES_VERSION OK: Server in standby mode | time=0.00 +=item B<--assume-prod> + +If specified, check if server in production mode is performed (--datadir is required). +The option is only relevant for (C). + +Example: + + postgres@db$./check_postgres.pl --action=checkpoint --datadir /var/lib/postgresql/8.3/main/ --assume-prod + POSTGRES_CHECKPOINT OK: Last checkpoint was 72 seconds ago | age=72;;300 mode=MASTER + =item B<-h> or B<--help> Displays a help screen with a summary of all actions and options. @@ -8132,6 +8189,8 @@ =head2 B pg_controldata executable must be available in the current path. Alternatively, you can set the environment variable C to the exact location of the pg_controldata executable, or you can specify C as the directory that it lives in. +It is also possible to use the special options I<--assume-prod> or +I<--assume-standby-mode>, if the mode found is not the one expected, a CRITICAL is emitted. At least one warning or critical argument must be set. From 63b2db3270f2d2383918e9c8ec7d5944b8a7ea7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Wed, 9 Nov 2011 18:56:00 +0800 Subject: [PATCH 04/42] Add cluster_id test for automatic testing too. --- MANIFEST | 1 + t/02_cluster_id.t | 80 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 t/02_cluster_id.t diff --git a/MANIFEST b/MANIFEST index aad59057..0c774447 100644 --- a/MANIFEST +++ b/MANIFEST @@ -17,6 +17,7 @@ t/02_autovac_freeze.t t/02_backends.t t/02_bloat.t t/02_checkpoint.t +t/02_cluster_id.t t/02_connection.t t/02_custom_query.t t/02_database_size.t diff --git a/t/02_cluster_id.t b/t/02_cluster_id.t new file mode 100644 index 00000000..6cab394c --- /dev/null +++ b/t/02_cluster_id.t @@ -0,0 +1,80 @@ +#!perl + +## Test the "checkpoint" action + +use 5.006; +use strict; +use warnings; +use Data::Dumper; +use Test::More tests => 14; +use lib 't','.'; +use CP_Testing; + +use vars qw/$dbh $result $SQL $t/; + +my $cp = CP_Testing->new( {default_action => 'cluster_id'} ); + +$dbh = $cp->test_database_handle(); + +my $S = q{Action 'cluster_id'}; +my $label = 'POSTGRES_CLUSTER_ID'; + +$t=qq{$S fails when called with an invalid option}; +like ($cp->run('foobar=12'), qr{Usage:}, $t); + +$t=qq{$S fails when called without warning or critical}; +like ($cp->run(''), qr{Must provide a 'warning' or 'critical'}, $t); + +$t=qq{$S fails when called with invalid warning option}; +like ($cp->run('-w foo'), qr{ERROR: .+'warning'.+must be an integer}, $t); + +$t=qq{$S fails when called with invalid critical option}; +like ($cp->run('-c foo'), qr{ERROR: .+'critical'.+must be an integer}, $t); + +$t=qq{$S fails when called without a datadir option and PGDATA is not set}; +delete $ENV{PGDATA}; +like ($cp->run('-c 10'), qr{^ERROR: Must supply a --datadir}, $t); + +$t=qq{$S fails when called with an invalid datadir option and PGDATA is not set}; +like ($cp->run('-c 10 --datadir=foobar'), qr{^ERROR: Invalid data_directory}, $t); + +$t = qq{$S rejects -w and -c together}; +is ($cp->run('-w 123 -c 123'), + qq{ERROR: Can only provide 'warning' OR 'critical' option\n}, $t); + +my $host = $cp->get_dbhost(); + +$t=qq{$S fails when called against a non datadir datadir}; +like ($cp->run(qq{-c 10 --datadir="$host"}), + qr{^ERROR:.+could not read the given data directory}, $t); + +$host =~ s/socket$//; + +$t = qq{$S notes mismatched cluster_id (warning)}; +like ($cp->run(qq{-w 123 --datadir="$host"}), + qr{$label WARNING: .* cluster_id:}, $t); + +$t = qq{$S notes mismatched cluster_id (critical)}; +like ($cp->run(qq{-c 123 --datadir="$host"}), + qr{$label CRITICAL: .* cluster_id:}, $t); + +$t = qq{$S self-identifies correctly}; +$result = $cp->run(qq{--critical 0 --datadir="$host"}); +like ($result, qr{^$label UNKNOWN: +cluster_id: \d+}, $t); + +my $true_cluster_id; +$true_cluster_id = $1 if $result =~ /cluster_id: (\d{19})/; + +$t = qq{$S accepts matching cluster_id}; +like ($cp->run(qq{-w $true_cluster_id --datadir="$host"}), + qr/OK.*\Qcluster_id: $true_cluster_id\E/, $t); + +$t=qq{$S returns the expected output for MRTG(failure)}; +like ($cp->run(qq{--mrtg 123 --output=MRTG --datadir="$host"}), + qr{^0\n0\n\n\d+}, $t); + +$t=qq{$S returns the expected output for MRTG(success)}; +like ($cp->run(qq{--mrtg $true_cluster_id --output=MRTG --datadir="$host"}), + qr{^1\n0\n\n\d+}, $t); + +exit; From e21fda81dd6940a51d8283a89410bfc5d7e62abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Wed, 9 Nov 2011 18:57:11 +0800 Subject: [PATCH 05/42] Add a test for checkpoint and --assume-standby-mode --- t/02_checkpoint.t | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/t/02_checkpoint.t b/t/02_checkpoint.t index 724e695b..dabee60d 100644 --- a/t/02_checkpoint.t +++ b/t/02_checkpoint.t @@ -6,7 +6,7 @@ use 5.006; use strict; use warnings; use Data::Dumper; -use Test::More tests => 13; +use Test::More tests => 14; use lib 't','.'; use CP_Testing; @@ -65,6 +65,10 @@ like ($cp->run(qq{-w 1 --datadir="$host"}), qr{^$label WARNING:}, $t); $t=qq{$S returns a critical when checkpoint older than critical option}; like ($cp->run(qq{-c 1 --datadir="$host"}), qr{^$label CRITICAL:}, $t); +# FIXME: no check for --assume-prod, it needs to have a cluster in this state +$t=qq{$S returns a critical when --assume-standby-mode on a non-standby}; +like ($cp->run(qq{-c 1000 --datadir="$host" --assume-standby-mode}), qr{^$label CRITICAL:.*mode=NOT STANDBY}, $t); + $t=qq{$S returns the correct number of seconds}; like ($cp->run(qq{-c 1 --datadir="$host"}), qr{was \d+ seconds ago}, $t); From 6aa297f1967292b63dfb340d7e89f0d17ecd3d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Wed, 9 Nov 2011 18:57:53 +0800 Subject: [PATCH 06/42] Add MRTG to test for settings_checksum --- t/02_settings_checksum.t | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/t/02_settings_checksum.t b/t/02_settings_checksum.t index 08decc8c..a5649754 100644 --- a/t/02_settings_checksum.t +++ b/t/02_settings_checksum.t @@ -6,7 +6,7 @@ use 5.006; use strict; use warnings; use Data::Dumper; -use Test::More tests => 8; +use Test::More tests => 10; use lib 't','.'; use CP_Testing; @@ -52,4 +52,12 @@ like ($cp->run('-c abcdabcdabcdabcdabcdabcdabcdabcd'), $t = qq{$S accepts matching checksum}; like ($cp->run("-w $true_checksum"), qr/OK.*\Qchecksum: $true_checksum\E/, $t); +$t=qq{$S returns the expected output for MRTG(failure)}; +like ($cp->run(qq{--mrtg 123 --output=MRTG}), + qr{^0\n0\n\n\d+}, $t); + +$t=qq{$S returns the expected output for MRTG(success)}; +like ($cp->run(qq{--mrtg $true_checksum --output=MRTG}), + qr{^1\n0\n\n\d+}, $t); + exit; From 3548f425ef41434c995949c5c229648f7b4b0240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Wed, 9 Nov 2011 19:10:40 +0800 Subject: [PATCH 07/42] Update history --- check_postgres.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/check_postgres.pl b/check_postgres.pl index c5e5d303..3539aa6c 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -9494,6 +9494,12 @@ =head1 HISTORY =over 4 +=item B + + Add the --assume-prod option (Cédric Villemain) + Add the cluster_id check (Cédric Villemain) + Improve settings_checksum and checkpoint tests (Cédric Villemain) + =item B Use the full path when getting sequence information for same_schema. From e89f10a2222024b8ea520bc301bdccf2eef21927 Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Wed, 23 Nov 2011 22:13:46 +0800 Subject: [PATCH 08/42] Change join to pg_user to a left join, as the database may be owned by a role. Thanks to Emmanuel Lesouef for the bug report and help in tracking this down. There are probably other incorrect inner joins to pg_user in the code. --- check_postgres.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/check_postgres.pl b/check_postgres.pl index 3539aa6c..1c0feae2 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -4073,7 +4073,7 @@ sub check_database_size { datname, usename FROM pg_database d -JOIN pg_user u ON (u.usesysid=d.datdba)$USERWHERECLAUSE +LEFT JOIN pg_user u ON (u.usesysid=d.datdba)$USERWHERECLAUSE }; if ($opt{perflimit}) { $SQL .= " ORDER BY 1 DESC LIMIT $opt{perflimit}"; From 6c4606d0185809e373006a13fd1229a5b49f48c4 Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Wed, 23 Nov 2011 22:16:07 +0800 Subject: [PATCH 09/42] Note latest fix. --- check_postgres.pl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/check_postgres.pl b/check_postgres.pl index 1c0feae2..8a71853a 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -9502,6 +9502,9 @@ =head1 HISTORY =item B + Do no do an inner join to pg_user when checking database size + (Greg Sabino Mullane; reported by Emmanuel Lesouef) + Use the full path when getting sequence information for same_schema. (Greg Sabino Mullane; reported by Cindy Wise) From 4b25a2b3f09b9c3613d1f0a0f52b869779f1f016 Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Thu, 24 Nov 2011 13:07:01 +0800 Subject: [PATCH 10/42] Exclude IIT from txn_time --- check_postgres.pl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/check_postgres.pl b/check_postgres.pl index 8a71853a..3b3872d3 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -7515,7 +7515,7 @@ sub check_txn_time { '', '', 'xact_start', - q{xact_start IS NOT NULL}); + q{xact_start IS NOT NULL AND current_query <> ' in transaction'}); return; @@ -9511,6 +9511,9 @@ =head1 HISTORY Better ordering of output for bloat check - make indexes as important as tables (Greg Sabino Mullane; reported by Jens Wilke) + Exclude idle in transaction queries from the txn_time action + (Greg Sabino Mullane; reported by Peter Eisentraut in bug 92) + Show the dbservice if it was used at top of same_schema output (Mike Blackwell) From 3d4b48725f11825b998780bf200bc589e3fe1df8 Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Sun, 27 Nov 2011 04:46:37 +0800 Subject: [PATCH 11/42] Revert bug 92 tweak, per point from Robert Treat. No more late night coding for me. #easilybrokenpromises --- check_postgres.pl | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index 3b3872d3..273c75f5 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -7508,14 +7508,14 @@ sub check_txn_idle { sub check_txn_time { - ## This is the same as check_txn_idle, but we want where the time is not null - ## as well as excluding any idle in transactions + ## This is the same as check_txn_idle, but we want where the + ## transaction start time is not null check_txn_idle('txntime', '', '', 'xact_start', - q{xact_start IS NOT NULL AND current_query <> ' in transaction'}); + q{xact_start IS NOT NULL'}); return; @@ -9511,9 +9511,6 @@ =head1 HISTORY Better ordering of output for bloat check - make indexes as important as tables (Greg Sabino Mullane; reported by Jens Wilke) - Exclude idle in transaction queries from the txn_time action - (Greg Sabino Mullane; reported by Peter Eisentraut in bug 92) - Show the dbservice if it was used at top of same_schema output (Mike Blackwell) From 2cc0e6e8a32266c45a62389f1a3e893831ae135c Mon Sep 17 00:00:00 2001 From: Euler Taveira de Oliveira Date: Sun, 27 Nov 2011 21:10:18 +0800 Subject: [PATCH 12/42] Fix xlog formula: ff000000 not ffffffff See http://eulerto.blogspot.com/2011/11/understanding-wal-nomenclature.html --- check_postgres.pl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index 273c75f5..2bfdd709 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -4702,7 +4702,7 @@ sub check_hot_standby_delay { next if ! defined $location; my ($x, $y) = split(/\//, $location); - $moffset = (hex("ffffffff") * hex($x)) + hex($y); + $moffset = (hex('ff000000') * hex($x)) + hex($y); $saved_db = $db if ! defined $saved_db; } @@ -4722,12 +4722,12 @@ sub check_hot_standby_delay { if (defined $receive) { my ($a, $b) = split(/\//, $receive); - $s_rec_offset = (hex("ffffffff") * hex($a)) + hex($b); + $s_rec_offset = (hex('ff000000') * hex($a)) + hex($b); } if (defined $replay) { my ($a, $b) = split(/\//, $replay); - $s_rep_offset = (hex("ffffffff") * hex($a)) + hex($b); + $s_rep_offset = (hex('ff000000') * hex($a)) + hex($b); } $saved_db = $db if ! defined $saved_db; @@ -9508,6 +9508,8 @@ =head1 HISTORY Use the full path when getting sequence information for same_schema. (Greg Sabino Mullane; reported by Cindy Wise) + Fix the formula for calculating xlog positions (Euler Taveira de Oliveira) + Better ordering of output for bloat check - make indexes as important as tables (Greg Sabino Mullane; reported by Jens Wilke) From 77b8b18b009a6ea83efe3876206a56ab41d3f5e0 Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Tue, 29 Nov 2011 03:37:39 +0800 Subject: [PATCH 13/42] Note bugzilla items, per recent email. --- README.dev | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.dev b/README.dev index 478225aa..eb482bd8 100644 --- a/README.dev +++ b/README.dev @@ -34,3 +34,8 @@ Login to the bucardo.org box, and then: * Email to check_postgres-announce with summary of changes +Once the new version is out there: + +* Make sure the new version is in the pulldown list of available versions. +* Go through and make sure all bugs solved in this release are marked as resolved + From 8418ddd38b3c34126b2eb5896209b8d4631ea05b Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Fri, 9 Dec 2011 12:00:27 +0800 Subject: [PATCH 14/42] Remove version 2.18.1 - going right to 2.19 --- check_postgres.pl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index 2bfdd709..db2cc31d 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -30,7 +30,7 @@ package check_postgres; $Data::Dumper::Indent = 2; $Data::Dumper::Useqq = 1; -our $VERSION = '2.18.1'; +our $VERSION = '2.19.0'; use vars qw/ %opt $PSQL $res $COM $SQL $db /; @@ -9497,10 +9497,10 @@ =head1 HISTORY =item B Add the --assume-prod option (Cédric Villemain) + Add the cluster_id check (Cédric Villemain) - Improve settings_checksum and checkpoint tests (Cédric Villemain) -=item B + Improve settings_checksum and checkpoint tests (Cédric Villemain) Do no do an inner join to pg_user when checking database size (Greg Sabino Mullane; reported by Emmanuel Lesouef) From eebee62e318ee3b1136c99e2b679a72bd821950a Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Fri, 9 Dec 2011 12:01:53 +0800 Subject: [PATCH 15/42] Make version 2.19.0 everywhere --- META.yml | 4 +-- Makefile.PL | 2 +- check_postgres.pl | 2 +- check_postgres.pl.html | 63 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 64 insertions(+), 7 deletions(-) diff --git a/META.yml b/META.yml index 4c5d2c80..ec7d3982 100644 --- a/META.yml +++ b/META.yml @@ -1,6 +1,6 @@ --- #YAML:1.0 name : check_postgres.pl -version : 2.18.1 +version : 2.19.0 abstract : Postgres monitoring script author: - Greg Sabino Mullane @@ -30,7 +30,7 @@ recommends: provides: check_postgres: file : check_postgres.pl - version : 2.18.1 + version : 2.19.0 keywords: - Postgres diff --git a/Makefile.PL b/Makefile.PL index a72ee4c7..26cdf96d 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -6,7 +6,7 @@ use strict; use warnings; use 5.006001; -my $VERSION = '2.18.1'; +my $VERSION = '2.19.0'; if ($VERSION =~ /_/) { print "WARNING! This is a test version ($VERSION) and should not be used in production!\n"; diff --git a/check_postgres.pl b/check_postgres.pl index db2cc31d..c844ec30 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -7708,7 +7708,7 @@ =head1 NAME B - a Postgres monitoring script for Nagios, MRTG, Cacti, and others -This documents describes check_postgres.pl version 2.18.1 +This documents describes check_postgres.pl version 2.19.0 =head1 SYNOPSIS diff --git a/check_postgres.pl.html b/check_postgres.pl.html index 99533f76..c0a527cc 100644 --- a/check_postgres.pl.html +++ b/check_postgres.pl.html @@ -42,6 +42,7 @@
  • backends
  • bloat
  • checkpoint
  • +
  • cluster_id
  • commitratio
  • connection
  • custom_query
  • @@ -121,7 +122,7 @@

    NAME

    check_postgres.pl - a Postgres monitoring script for Nagios, MRTG, Cacti, and others

    -

    This documents describes check_postgres.pl version 2.18.0

    +

    This documents describes check_postgres.pl version 2.19.0


    @@ -329,6 +330,16 @@

    OTHER OPTIONS

    postgres@db$./check_postgres.pl --action=version --warning=8.1 --datadir /var/lib/postgresql/8.3/main/ --assume-standby-mode POSTGRES_VERSION OK: Server in standby mode | time=0.00 +
    --assume-prod
    + +
    +

    If specified, check if server in production mode is performed (--datadir is required). +The option is only relevant for (symlink: check_postgres_checkpoint).

    +

    Example:

    +
    +    postgres@db$./check_postgres.pl --action=checkpoint --datadir /var/lib/postgresql/8.3/main/ --assume-prod
    +    POSTGRES_CHECKPOINT OK: Last checkpoint was 72 seconds ago | age=72;;300 mode=MASTER
    +
    -h or --help
    @@ -586,12 +597,32 @@

    checkpoint

    was run, as determined by parsing the call to pg_controldata. Because of this, the pg_controldata executable must be available in the current path. Alternatively, you can set the environment variable PGCONTROLDATA to the exact location of the pg_controldata -executable, or you can specify PGBINDIR as the directory that it lives in.

    +executable, or you can specify PGBINDIR as the directory that it lives in. +It is also possible to use the special options --assume-prod or +--assume-standby-mode, if the mode found is not the one expected, a CRITICAL is emitted.

    At least one warning or critical argument must be set.

    This action requires the Date::Parse module.

    For MRTG or simple output, returns the number of seconds.

    +

    cluster_id

    +

    (symlink: check_postgres_cluster-id) Checks that the Database System Identifier +provided by pg_controldata is the same as last time you checked. This must run on the same +server as the database that is being checked (e.g. the -h flag will not work). +Either the --warning or the --critical option should be given, but not both. The value +of each one is the cluster identifier, an integer value. You can run with the special --critical=0 option +to find out an existing cluster identifier.

    +

    Example 1: Find the initial identifier

    +
    +  check_postgres_cluster_id --critical=0 --datadir=/var//lib/postgresql/9.0/main
    +

    Example 2: Make sure the cluster is the same and warn if not, using the result from above.

    +
    +  check_postgres_cluster_id  --critical=5633695740047915135
    +

    For MRTG output, returns a 1 or 0 indicating success of failure of the identifier to match. A +identifier must be provided as the --mrtg argument. The fourth line always gives the +current identifier.

    +

    +

    commitratio

    (symlink: check_postgres_commitratio) Checks the commit ratio of all databases and complains when they are too low. There is no need to run this command more than once per database cluster. @@ -1250,7 +1281,7 @@

    query_time

    are 'seconds', 'minutes', 'hours', or 'days'. Each may be written singular or abbreviated to just the first letter. If no units are given, the unit is assumed to be seconds.

    -

    This action requires Postgres 8.3 or better.

    +

    This action requires Postgres 8.1 or better.

    Example 1: Give a warning if any query has been running longer than 3 minutes, and a critical if longer than 5 minutes.

       check_postgres_query_time --port=5432 --warning='3 minutes' --critical='5 minutes'
    @@ -1723,6 +1754,32 @@

    MAILING LIST

    HISTORY

    Items not specifically attributed are by GSM (Greg Sabino Mullane).

    +
    Version 2.19.0
    + +
    +
    +  Add the --assume-prod option (Cédric Villemain)
    +
    +  Add the cluster_id check (Cédric Villemain)
    +
    +  Improve settings_checksum and checkpoint tests (Cédric Villemain)
    +
    +  Do no do an inner join to pg_user when checking database size
    +    (Greg Sabino Mullane; reported by Emmanuel Lesouef)
    +
    +  Use the full path when getting sequence information for same_schema.
    +    (Greg Sabino Mullane; reported by Cindy Wise)
    +
    +  Fix the formula for calculating xlog positions (Euler Taveira de Oliveira)
    +
    +  Better ordering of output for bloat check - make indexes as important
    +    as tables (Greg Sabino Mullane; reported by Jens Wilke)
    +
    +  Show the dbservice if it was used at top of same_schema output
    +    (Mike Blackwell)
    +
    +  Better installation paths (Greg Sabino Mullane, per bug 53)
    +
    Version 2.18.0 October 2, 2011
    From e16d325d33b7af15ef165ab6fc9011275247575f Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Fri, 9 Dec 2011 12:02:27 +0800 Subject: [PATCH 16/42] Ignore the MYMETA auto-generated files --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9cf0fee2..4489c953 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ blib/* test_database_check_postgres* *.tmp cover_db/ -check_postgres- \ No newline at end of file +check_postgres- +MYMETA.* From 91a7002887c97f66a79a6eed95db3adcac71fee6 Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Mon, 16 Jan 2012 22:26:09 +0800 Subject: [PATCH 17/42] Bump to 2012 --- README | 4 ++-- check_postgres.pl | 2 +- check_postgres.pl.html | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README b/README index a060d147..7dbec71b 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -check_postgres is Copyright (C) 2007-2011, Greg Sabino Mullane +check_postgres is Copyright (C) 2007-2012, Greg Sabino Mullane This is check_postgres, a monitoring tool for Postgres. @@ -76,7 +76,7 @@ https://mail.endcrypt.com/mailman/listinfo/check_postgres-commit COPYRIGHT: ---------- - Copyright (c) 2007-2011 Greg Sabino Mullane + Copyright (c) 2007-2012 Greg Sabino Mullane LICENSE INFORMATION: diff --git a/check_postgres.pl b/check_postgres.pl index c844ec30..c14ed119 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -10143,7 +10143,7 @@ =head1 NAGIOS EXAMPLES =head1 LICENSE AND COPYRIGHT -Copyright (c) 2007-2011 Greg Sabino Mullane . +Copyright (c) 2007-2012 Greg Sabino Mullane . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/check_postgres.pl.html b/check_postgres.pl.html index c0a527cc..a9996e7e 100644 --- a/check_postgres.pl.html +++ b/check_postgres.pl.html @@ -2589,7 +2589,7 @@

    NAGIOS EXAMPLES


    LICENSE AND COPYRIGHT

    -

    Copyright (c) 2007-2011 Greg Sabino Mullane <greg@endpoint.com>.

    +

    Copyright (c) 2007-2012 Greg Sabino Mullane <greg@endpoint.com>.

    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    
    From 2b28a5ba37d9b8c4c3e3a05aaa178d65505a14b0 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Mon, 16 Jan 2012 22:27:12 +0800
    Subject: [PATCH 18/42] Remove tabs
    
    ---
     check_postgres.pl | 10 +++++-----
     1 file changed, 5 insertions(+), 5 deletions(-)
    
    diff --git a/check_postgres.pl b/check_postgres.pl
    index c14ed119..0b5ede8d 100755
    --- a/check_postgres.pl
    +++ b/check_postgres.pl
    @@ -1534,7 +1534,7 @@ sub make_sure_mode_is {
         $db->{host} = '';
     
         ## Run pg_controldata, grab the mode
    -	$res = open_controldata();
    +    $res = open_controldata();
     
         my $regex = msg('checkmode-state');
         if ($res !~ /$regex\s*(.+)/) { ## no critic (ProhibitUnusedCapture)
    @@ -3159,8 +3159,8 @@ sub open_controldata {
             ndie msg('checkpoint-badver2');
         }
     
    -	## return the pg_controldata output
    -	return $res;
    +    ## return the pg_controldata output
    +    return $res;
     }
     
     
    @@ -3712,7 +3712,7 @@ sub check_checkpoint {
         $db->{host} = '';
     
         ## Run pg_controldata, grab the time
    -	$res = open_controldata();
    +    $res = open_controldata();
     
         my $regex = msg('checkpoint-po');
         if ($res !~ /$regex\s*(.+)/) { ## no critic (ProhibitUnusedCapture)
    @@ -3803,7 +3803,7 @@ sub check_cluster_id {
         $db->{host} = '';
     
         ## Run pg_controldata, grab the cluster-id
    -	$res = open_controldata();
    +    $res = open_controldata();
     
         my $regex = msg('checkcluster-id');
         if ($res !~ /$regex\s*(.+)/) { ## no critic (ProhibitUnusedCapture)
    
    From dd0990731b6c181ff53b3eddff0636ba941e261b Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Mon, 16 Jan 2012 22:45:51 +0800
    Subject: [PATCH 19/42] More tabs
    
    ---
     t/CP_Testing.pm | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/t/CP_Testing.pm b/t/CP_Testing.pm
    index 6c8cf97f..530271ce 100644
    --- a/t/CP_Testing.pm
    +++ b/t/CP_Testing.pm
    @@ -332,7 +332,7 @@ sub test_database_handle {
         $dbh->do('CREATE DATABASE ardala');
         $dbh->do('CREATE LANGUAGE plpgsql');
         $dbh->do('CREATE LANGUAGE plperlu');
    -	$dbh->do("CREATE SCHEMA $fakeschema");
    +    $dbh->do("CREATE SCHEMA $fakeschema");
         $dbh->{AutoCommit} = 0;
         $dbh->{RaiseError} = 1;
     
    
    From 1814c40cbbca54b1ff01c35d39a5c31aa317189d Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Mon, 16 Jan 2012 22:47:44 +0800
    Subject: [PATCH 20/42] Getting tired of these !@#$!@#%! tabs in this !~@#$!@#$
     code
    
    ---
     t/03_translations.t | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/t/03_translations.t b/t/03_translations.t
    index d321f06b..b8263b4b 100644
    --- a/t/03_translations.t
    +++ b/t/03_translations.t
    @@ -178,7 +178,7 @@ for my $l (sort keys %complete_langs) {
             my $lval = $msg{$l}{$msg}->[1];
             my $indent = $msg{$l}{$msg}->[0];
             next if $language eq 'French' and ($msg eq 'PID' or $msg eq 'port' or $msg eq 'pgbouncer-pool'
    -								   or $msg eq 'index' or $msg eq 'table' or $msg eq 'transactions');
    +            or $msg eq 'index' or $msg eq 'table' or $msg eq 'transactions');
             if ($val eq $lval and $indent) {
                 fail qq{Message '$msg' in language $language appears to not be translated, but it not marked as such};
                 $ok = 0;
    
    From cf7897616bea1e984710b7ccdf41b6f1988d1044 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Tue, 17 Jan 2012 00:01:57 +0800
    Subject: [PATCH 21/42] Add some debugging to the perlcritic test
    
    ---
     t/99_perlcritic.t | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/t/99_perlcritic.t b/t/99_perlcritic.t
    index 4c8cfe0f..3bb7610f 100644
    --- a/t/99_perlcritic.t
    +++ b/t/99_perlcritic.t
    @@ -41,7 +41,9 @@ for my $filename (qw{Makefile.PL check_postgres.pl t/CP_Testing.pm}) {
         -e $filename or die qq{Could not find "$filename"!};
         open my $oldstderr, '>&', \*STDERR or die 'Could not dupe STDERR';
         close STDERR or die qq{Could not close STDERR: $!};
    +	diag "Running perlcritic on file $filename";
         my @vio = $critic->critique($filename);
    +	diag "Done";
         open STDERR, '>&', $oldstderr or die 'Could not recreate STDERR'; ## no critic
         close $oldstderr or die qq{Could not close STDERR copy: $!};
         my $vios = 0;
    
    From d5ba8787f2006845cf79daba9913508aa90ab78c Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Tue, 17 Jan 2012 00:49:48 +0800
    Subject: [PATCH 22/42] Make sure we do not force cluster ids to an int, else
     we get exponential notation.
    
    ---
     check_postgres.pl | 8 +++++---
     1 file changed, 5 insertions(+), 3 deletions(-)
    
    diff --git a/check_postgres.pl b/check_postgres.pl
    index 0b5ede8d..a946c972 100755
    --- a/check_postgres.pl
    +++ b/check_postgres.pl
    @@ -2879,8 +2879,10 @@ sub validate_range {
                 ) {
                 ndie msg('range-warnbig');
             }
    -        $warning = int $warning if length $warning;
    -        $critical = int $critical if length $critical;
    +        if ($type !~ /string/) {
    +            $warning = int $warning if length $warning;
    +            $critical = int $critical if length $critical;
    +        }
         }
         elsif ('restringex' eq $type) {
             if (! length $critical and ! length $warning) {
    @@ -3798,7 +3800,7 @@ sub check_cluster_id {
         ## Example:
         ##  check_postgres_cluster_id --critical="5633695740047915125"
     
    -    my ($warning, $critical) = validate_range({type => 'integer', onlyone => 1});
    +    my ($warning, $critical) = validate_range({type => 'integer_string', onlyone => 1});
     
         $db->{host} = '';
     
    
    From f59a576f7c77d914f1249b0e57ef56fa5230eae3 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Tue, 17 Jan 2012 00:57:16 +0800
    Subject: [PATCH 23/42] Typo in SQL
    
    ---
     check_postgres.pl | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/check_postgres.pl b/check_postgres.pl
    index a946c972..2bc23d1b 100755
    --- a/check_postgres.pl
    +++ b/check_postgres.pl
    @@ -7517,7 +7517,7 @@ sub check_txn_time {
                        '',
                        '',
                        'xact_start',
    -                   q{xact_start IS NOT NULL'});
    +                   q{xact_start IS NOT NULL});
     
         return;
     
    
    From 510267d14b5e25b92a4bad112349707efd58ec11 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Tue, 17 Jan 2012 00:59:08 +0800
    Subject: [PATCH 24/42] Translation cleanups
    
    ---
     check_postgres.pl | 11 ++++++++---
     1 file changed, 8 insertions(+), 3 deletions(-)
    
    diff --git a/check_postgres.pl b/check_postgres.pl
    index 2bc23d1b..d2e5c306 100755
    --- a/check_postgres.pl
    +++ b/check_postgres.pl
    @@ -102,9 +102,9 @@ package check_postgres;
         'checkcluster-id'    => q{Database system identifier:},
         'checkcluster-msg'   => q{cluster_id: $1},
         'checkcluster-nomrtg'=> q{Must provide a number via the --mrtg option},
    -    'checkmode-state'    => q{Database cluster state:},
    -    'checkmode-recovery' => q{in archive recovery},
         'checkmode-prod'     => q{in production},
    +    'checkmode-recovery' => q{in archive recovery},
    +    'checkmode-state'    => q{Database cluster state:},
         'checkpoint-baddir'  => q{Invalid data_directory: "$1"},
         'checkpoint-baddir2' => q{pg_controldata could not read the given data directory: "$1"},
         'checkpoint-badver'  => q{Failed to run pg_controldata - probably the wrong version ($1)},
    @@ -349,8 +349,12 @@ package check_postgres;
         'bloat-nomin'        => q{aucune relation n'atteint le critère minimum de fragmentation},
         'bloat-table'        => q{(db $1) table $2.$3 lignes:$4 pages:$5 devrait être:$6 ($7X) place perdue:$8 ($9)},
         'bug-report'         => q{Merci de rapporter ces d??tails ?? check_postgres@bucardo.org:},
    -    'checkmode-state'    => q{État de l'instance :},
    +'checkcluster-id'    => q{Database system identifier:},
    +'checkcluster-msg'   => q{cluster_id: $1},
    +'checkcluster-nomrtg'=> q{Must provide a number via the --mrtg option},
    +'checkmode-prod'     => q{in production},
         'checkmode-recovery' => q{en restauration d'archives},
    +    'checkmode-state'    => q{État de l'instance :},
         'checkpoint-baddir'  => q{data_directory invalide : "$1"},
         'checkpoint-baddir2' => q{pg_controldata n'a pas pu lire le répertoire des données indiqué : « $1 »},
         'checkpoint-badver'  => q{Échec lors de l'exécution de pg_controldata - probablement la mauvaise version ($1)},
    @@ -410,6 +414,7 @@ package check_postgres;
         'logfile-stderr'     => q{La sortie des traces a été redirigés stderr : merci de fournir un nom de fichier},
         'logfile-syslog'     => q{La base de données utiliser syslog, merci de spécifier le chemin avec l'option --logfile (fac=$1)},
         'mode-standby'       => q{Serveur en mode standby},
    +'mode'               => q{mode},
         'mrtg-fail'          => q{Échec de l'action $1 : $2},
         'new-ver-nocver'     => q{N'a pas pu t??l??charger les informations de version pour $1},
         'new-ver-badver'     => q{N'a pas pu analyser les informations de version pour $1},
    
    From 9e150098d142994a2c3ad1cf5a49a61cf89db009 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Tue, 17 Jan 2012 01:38:43 +0800
    Subject: [PATCH 25/42] Spell check tweaks
    
    ---
     check_postgres.pl |  2 +-
     t/99_spellcheck.t | 26 ++++++++++++++++++++++++--
     2 files changed, 25 insertions(+), 3 deletions(-)
    
    diff --git a/check_postgres.pl b/check_postgres.pl
    index d2e5c306..4a2afd22 100755
    --- a/check_postgres.pl
    +++ b/check_postgres.pl
    @@ -1927,7 +1927,7 @@ sub finishup {
     ## Check how long since the last checkpoint
     check_checkpoint() if $action eq 'checkpoint';
     
    -## Check the Datasbae System Identifier
    +## Check the Database System Identifier
     check_cluster_id() if $action eq 'cluster_id';
     
     ## Check for disabled triggers
    diff --git a/t/99_spellcheck.t b/t/99_spellcheck.t
    index 957d4b18..4ac34269 100644
    --- a/t/99_spellcheck.t
    +++ b/t/99_spellcheck.t
    @@ -152,6 +152,7 @@ Mullane
     Nagios
     ok
     PGP
    +Postgres
     Sabino
     SQL
     http
    @@ -160,7 +161,9 @@ login
     perl
     pgbouncer
     pgBouncer
    +plpgsql
     postgres
    +Pre
     runtime
     Schemas
     selectall
    @@ -199,7 +202,6 @@ lang
     li
     listinfo
     moz
    -Postgres
     pre
     px
     ul
    @@ -212,6 +214,8 @@ xmlns
     Abrigo
     Albe
     alice
    +Andras
    +Andreas
     ARG
     args
     artemus
    @@ -236,6 +240,7 @@ checkpostgresrc
     checksum
     checksums
     checktype
    +Christoph
     commitratio
     commitratio
     conf
    @@ -252,6 +257,7 @@ Cwd
     cylon
     datadir
     datallowconn
    +Davide
     dbhost
     dbname
     dbpass
    @@ -269,6 +275,7 @@ df
     dir
     dric
     dylan
    +EB
     Eisentraut
     emma
     endcrypt
    @@ -295,11 +302,13 @@ garrett
     Getopt
     GetOptions
     Glaesemann
    +Glyn
     greg
     grimm
     GSM
     gtld
     Guettler
    +Guillaume
     Gurjeet
     hardcode
     HiRes
    @@ -326,6 +335,7 @@ includeuser
     Ioannis
     ioguix
     Jehan
    +Jens
     Kabalin
     Kirkwood
     klatch
    @@ -335,6 +345,7 @@ Krishnamurthy
     lancre
     Laurenz
     Lelarge
    +Lesouef
     listinfo
     localhost
     localtime
    @@ -345,9 +356,11 @@ maindatabase
     Makefile
     Mallett
     mallory
    +Marti
     maxalign
     maxwait
     mcp
    +MERCHANTABILITY
     MINIPAGES
     MINPAGES
     minvalue
    @@ -380,6 +393,7 @@ notrigger
     ok
     Oliveira
     oper
    +Optimizations
     oskar
     pageslots
     param
    @@ -391,6 +405,7 @@ perfname
     perfs
     petabytes
     pgb
    +PGBINDIR
     pgbouncer's
     PGCONTROLDATA
     PGDATA
    @@ -399,12 +414,15 @@ PGHOST
     pgpass
     PGPORT
     PGSERVICE
    +pgsql
     PGUSER
     pid
    +plasmid
     plugin
     pluto
    -Postgres
    +POSTGRES
     postgresql
    +PostgreSQL
     postgresrc
     prepend
     prereqs
    @@ -476,6 +494,7 @@ tnm
     Tolley
     tup
     undef
    +unlinked
     upd
     uptime
     USERNAME
    @@ -489,9 +508,12 @@ wal
     WAL
     watson
     Westwood
    +wget
     wiki
    +Wilke
     wilkins
     xact
     xlog
    +Yamada
     Zwerschke
     
    
    From c188d098e8aa304b47c19dfdb283b14942aea640 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Tue, 17 Jan 2012 22:17:59 +0800
    Subject: [PATCH 26/42] Have MRTG show a set message, for times when we end up
     there indirectly.
    
    ---
     check_postgres.pl | 18 +++++++++++++++++-
     1 file changed, 17 insertions(+), 1 deletion(-)
    
    diff --git a/check_postgres.pl b/check_postgres.pl
    index 4a2afd22..d6af95cc 100755
    --- a/check_postgres.pl
    +++ b/check_postgres.pl
    @@ -1592,7 +1592,23 @@ sub finishup {
         ## Final output
         ## These are meant to be compact and terse: sometimes messages go to pagers
     
    -    $MRTG and do_mrtg_stats();
    +    if ($MRTG) {
    +        ## Try hard to ferret out a message in case we short-circuited here
    +        my $msg = [[]];
    +        if (keys %critical) {
    +            ($msg) = values %critical;
    +        }
    +        elsif (keys %warning) {
    +            ($msg) = values %warning;
    +        }
    +        elsif (keys %ok) {
    +            ($msg) = values %ok;
    +        }
    +        elsif (keys %unknown) {
    +            ($msg) = values %unknown;
    +        }
    +        do_mrtg_stats($msg->[0][0]);
    +    }
     
         $action =~ s/^\s*(\S+)\s*$/$1/;
         my $service = sprintf "%s$action", $FANCYNAME ? 'postgres_' : '';
    
    From 87f15d5df5886c594115dfde9c7469a2b528dbc3 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Wed, 18 Jan 2012 01:52:43 +0800
    Subject: [PATCH 27/42] Tweaks for better "fakeschema" in the tests.
    
    ---
     t/02_backends.t | 30 +++++++++++++-----------------
     t/CP_Testing.pm | 31 +++++++++++++++++++++++++++++--
     2 files changed, 42 insertions(+), 19 deletions(-)
    
    diff --git a/t/02_backends.t b/t/02_backends.t
    index 4dd03b67..d8e6c50c 100644
    --- a/t/02_backends.t
    +++ b/t/02_backends.t
    @@ -6,7 +6,7 @@ use 5.006;
     use strict;
     use warnings;
     use Data::Dumper;
    -use Test::More tests => 53;
    +use Test::More tests => 52;
     use lib 't','.';
     use CP_Testing;
     
    @@ -16,6 +16,9 @@ my $cp = CP_Testing->new( {default_action => 'backends'} );
     
     $dbh = $cp->test_database_handle();
     
    +## Remove any old fake schema
    +$cp->drop_schema_if_exists();
    +
     my $S = q{Action 'backends'};
     my $label = 'POSTGRES_BACKENDS';
     
    @@ -129,18 +132,13 @@ $num = $goodver ? 7 : 8;
     like ($cp->run("-c -$num"), qr{^$label CRITICAL}, $t);
     
     $t=qq{$S works when no items caught by pg_stat_activity};
    -
    -$cp->drop_schema_if_exists();
    -$cp->create_fake_pg_table('pg_stat_activity');
    -like ($cp->run(), qr{^$label OK: .+No connections}, $t);
    -
    -$t=qq{$S returns correct MRTG output when no rows};
    -is ($cp->run('--output=MRTG'), qq{0\n0\n\nDB=postgres Max connections=10\n}, $t);
    +$cp->create_fake_pg_table('pg_stat_activity','', ' WHERE procpid = pg_backend_pid()');
    +like ($cp->run(), qr{^$label OK: .+1 of }, $t);
     
     $t=qq{$S fails as expected when max_connections cannot be determined};
     $cp->create_fake_pg_table('pg_settings');
     like ($cp->run(), qr{^$label UNKNOWN: .+max_connections}, $t);
    -$cp->drop_schema_if_exists();
    +$cp->remove_fake_pg_table('pg_settings');
     
     $t=qq{$S works when include forces no matches};
     like ($cp->run('--include=foobar'), qr{^$label OK: .+No connections}, $t);
    @@ -150,10 +148,10 @@ SKIP: {
         $goodver or skip 'Cannot test backends completely with older versions of Postgres', 2;
     
         $t=qq{$S returns correct MRTG output when rows found};
    -    is ($cp->run('--output=MRTG'), qq{3\n0\n\nDB=postgres Max connections=10\n}, $t);
    +    like ($cp->run('--output=MRTG'), qr{^1\n0\n\nDB=postgres}, $t);
     
         $t=qq{$S works when include has valid database};
    -    like ($cp->run('--include=postgres'), qr{^$label OK: .+3 of 10}, $t);
    +    like ($cp->run('--include=postgres'), qr{^$label OK: .+1 of 10}, $t);
     }
     
     $t=qq{$S works when exclude forces no matches};
    @@ -164,16 +162,16 @@ SKIP: {
         $goodver or skip 'Cannot test backends completely with older versions of Postgres', 4;
     
         $t=qq{$S works when exclude excludes nothing};
    -    like ($cp->run('--exclude=foobar'), qr{^$label OK: .+3 of 10}, $t);
    +    like ($cp->run('--exclude=foobar'), qr{^$label OK: .+1 of 10}, $t);
     
         $t=qq{$S works when include and exclude make a match};
    -    like ($cp->run('--exclude=postgres --include=postgres'), qr{^$label OK: .+3 of 10}, $t);
    +    like ($cp->run('--exclude=postgres --include=postgres'), qr{^$label OK: .+1 of 10}, $t);
     
         $t=qq{$S works when include and exclude make a match};
    -    like ($cp->run('--include=postgres --exclude=postgres'), qr{^$label OK: .+3 of 10}, $t);
    +    like ($cp->run('--include=postgres --exclude=postgres'), qr{^$label OK: .+1 of 10}, $t);
     
         $t=qq{$S returned correct performance data with include};
    -    like ($cp->run('--include=postgres'), qr{ \| time=\d\.\d\ds postgres=3;9;9;0;10}, $t);
    +    like ($cp->run('--include=postgres'), qr{ \| time=\d\.\d\ds postgres=1}, $t);
     }
     
     my %dbh;
    @@ -184,6 +182,4 @@ for my $num (1..8) {
     $t=qq{$S returns critical when too many clients to even connect};
     like ($cp->run('-w -10'), qr{^$label CRITICAL: .+too many connections}, $t);
     
    -$cp->drop_schema_if_exists();
    -
     exit;
    diff --git a/t/CP_Testing.pm b/t/CP_Testing.pm
    index 530271ce..a72a957c 100644
    --- a/t/CP_Testing.pm
    +++ b/t/CP_Testing.pm
    @@ -508,6 +508,7 @@ sub create_fake_pg_table {
         my $self = shift;
         my $name = shift || die;
         my $args = shift || '';
    +	my $where = shift || '';
         my $dbh = $self->{dbh} || die;
         my $dbuser = $self->{testuser} || die;
         if ($self->schema_exists($dbh,$fakeschema)) {
    @@ -523,7 +524,10 @@ sub create_fake_pg_table {
             $funcargs = qq{($funcargs)};
         }
     
    -    $dbh->do("CREATE TABLE $fakeschema.$name AS SELECT * FROM $name$funcargs LIMIT 0");
    +	my $SQL = "CREATE TABLE $fakeschema.$name AS SELECT * FROM $name$funcargs$where ";
    +	$SQL .= $where ? 'LIMIT 1' : 'LIMIT 0';
    +
    +    $dbh->do($SQL);
     
         if ($args) {
             $self->drop_function_if_exists($fakeschema,$name,$args);
    @@ -537,6 +541,28 @@ sub create_fake_pg_table {
     } ## end of create_fake_pg_table
     
     
    +sub remove_fake_pg_table {
    +
    +    my $self = shift;
    +    my $name = shift || die;
    +    my $dbh = $self->{dbh} || die;
    +    my $dbuser = $self->{testuser} || die;
    +    if (! $self->schema_exists($dbh,$fakeschema)) {
    +		## No schema means no table!
    +		return;
    +	}
    +
    +	my $SQL = "DROP TABLE $fakeschema.$name";
    +
    +    $dbh->do($SQL);
    +
    +    $dbh->commit();
    +
    +    return;
    +
    +} ## end of remove_fake_pg_table
    +
    +
     sub get_fake_schema {
         return $fakeschema;
     }
    @@ -625,7 +651,8 @@ sub drop_table_if_exists {
         my $count = $dbh->selectall_arrayref($SQL)->[0][0];
         if ($count) {
             $dbh->{Warn} = 0;
    -        $dbh->do("DROP TABLE $name CASCADE");
    +		my $fullname = $schema ? "$schema.$name" : $name;
    +        $dbh->do("DROP TABLE $fullname CASCADE");
             $dbh->{Warn} = 1;
             $dbh->commit();
         }
    
    From 1903ced4bb301757fbcab12eb4fb5ce9fe67ebb7 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Wed, 18 Jan 2012 01:58:25 +0800
    Subject: [PATCH 28/42] Remove tabs
    
    ---
     t/CP_Testing.pm | 16 ++++++++--------
     1 file changed, 8 insertions(+), 8 deletions(-)
    
    diff --git a/t/CP_Testing.pm b/t/CP_Testing.pm
    index a72a957c..05d6a1bf 100644
    --- a/t/CP_Testing.pm
    +++ b/t/CP_Testing.pm
    @@ -508,7 +508,7 @@ sub create_fake_pg_table {
         my $self = shift;
         my $name = shift || die;
         my $args = shift || '';
    -	my $where = shift || '';
    +    my $where = shift || '';
         my $dbh = $self->{dbh} || die;
         my $dbuser = $self->{testuser} || die;
         if ($self->schema_exists($dbh,$fakeschema)) {
    @@ -524,8 +524,8 @@ sub create_fake_pg_table {
             $funcargs = qq{($funcargs)};
         }
     
    -	my $SQL = "CREATE TABLE $fakeschema.$name AS SELECT * FROM $name$funcargs$where ";
    -	$SQL .= $where ? 'LIMIT 1' : 'LIMIT 0';
    +    my $SQL = "CREATE TABLE $fakeschema.$name AS SELECT * FROM $name$funcargs$where ";
    +    $SQL .= $where ? 'LIMIT 1' : 'LIMIT 0';
     
         $dbh->do($SQL);
     
    @@ -548,11 +548,11 @@ sub remove_fake_pg_table {
         my $dbh = $self->{dbh} || die;
         my $dbuser = $self->{testuser} || die;
         if (! $self->schema_exists($dbh,$fakeschema)) {
    -		## No schema means no table!
    -		return;
    -	}
    +        ## No schema means no table!
    +        return;
    +    }
     
    -	my $SQL = "DROP TABLE $fakeschema.$name";
    +    my $SQL = "DROP TABLE $fakeschema.$name";
     
         $dbh->do($SQL);
     
    @@ -651,7 +651,7 @@ sub drop_table_if_exists {
         my $count = $dbh->selectall_arrayref($SQL)->[0][0];
         if ($count) {
             $dbh->{Warn} = 0;
    -		my $fullname = $schema ? "$schema.$name" : $name;
    +        my $fullname = $schema ? "$schema.$name" : $name;
             $dbh->do("DROP TABLE $fullname CASCADE");
             $dbh->{Warn} = 1;
             $dbh->commit();
    
    From b01a2195088178de0772b956bfcdfa24a143dffc Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Wed, 18 Jan 2012 03:21:20 +0800
    Subject: [PATCH 29/42] Clear temp schema
    
    ---
     t/02_logfile.t | 3 +++
     1 file changed, 3 insertions(+)
    
    diff --git a/t/02_logfile.t b/t/02_logfile.t
    index 743a3639..15de979d 100644
    --- a/t/02_logfile.t
    +++ b/t/02_logfile.t
    @@ -17,6 +17,9 @@ my $cp = CP_Testing->new( {default_action => 'logfile'} );
     
     $dbh = $cp->test_database_handle();
     
    +## Remove any old fake schema
    +$cp->drop_schema_if_exists();
    +
     $host = $cp->get_host();
     $dbname = $cp->get_dbname();
     
    
    From a060bd13796b9fc439cd108ab4f0fa7106145a1f Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Wed, 18 Jan 2012 03:50:04 +0800
    Subject: [PATCH 30/42] Try to wrap failing Perl::Critic calls in an eval. Does
     not work.
    
    ---
     t/99_perlcritic.t | 14 +++++++++++---
     1 file changed, 11 insertions(+), 3 deletions(-)
    
    diff --git a/t/99_perlcritic.t b/t/99_perlcritic.t
    index 3bb7610f..4a1e449e 100644
    --- a/t/99_perlcritic.t
    +++ b/t/99_perlcritic.t
    @@ -41,9 +41,17 @@ for my $filename (qw{Makefile.PL check_postgres.pl t/CP_Testing.pm}) {
         -e $filename or die qq{Could not find "$filename"!};
         open my $oldstderr, '>&', \*STDERR or die 'Could not dupe STDERR';
         close STDERR or die qq{Could not close STDERR: $!};
    -	diag "Running perlcritic on file $filename";
    -    my @vio = $critic->critique($filename);
    -	diag "Done";
    +	my @vio;
    +	my $ranok = 0;
    +	eval {
    +		@vio = $critic->critique($filename);
    +		$ranok = 1;
    +	};
    +	if (! $ranok) {
    +		pass "Perl::Critic failed for file $filename. Error was: $@\n";
    +		$@ = undef;
    +		next;
    +	}
         open STDERR, '>&', $oldstderr or die 'Could not recreate STDERR'; ## no critic
         close $oldstderr or die qq{Could not close STDERR copy: $!};
         my $vios = 0;
    
    From 9c2ff785584a9717d1fbe1d8b092b48f2c6ea777 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Wed, 18 Jan 2012 05:03:16 +0800
    Subject: [PATCH 31/42] Omit Variables::ProhibitUselessInitialization as it has
     an internal error.
    
    ---
     perlcriticrc | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/perlcriticrc b/perlcriticrc
    index a83b8443..b7579658 100644
    --- a/perlcriticrc
    +++ b/perlcriticrc
    @@ -90,6 +90,7 @@ stop_words = Mullane Nagios Slony Slony's nols salesrep psql dbname postgres USE
     
     [-Variables::ProhibitPackageVars]
     [-Variables::ProhibitPunctuationVars]
    +[-Variables::ProhibitUselessInitialization]
     [-Variables::RequireInitializationForLocalVars]
     [-Variables::RequireLexicalLoopIterators]
     [-Variables::RequireLocalizedPunctuationVars]
    
    From ef761908724afb77fcf321c068dec962027dc2cd Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Wed, 18 Jan 2012 08:43:24 +0800
    Subject: [PATCH 32/42] Perl::Critic inspired changes
    
    ---
     check_postgres.pl        | 56 +++++++++++++++++++++-------------------
     perlcriticrc             | 12 ++++++---
     t/00_release.t           |  4 +--
     t/02_custom_query.t      |  2 +-
     t/02_same_schema.t       |  6 ++---
     t/02_settings_checksum.t |  2 +-
     t/CP_Testing.pm          |  4 +--
     7 files changed, 45 insertions(+), 41 deletions(-)
    
    diff --git a/check_postgres.pl b/check_postgres.pl
    index d6af95cc..c546c99e 100755
    --- a/check_postgres.pl
    +++ b/check_postgres.pl
    @@ -904,7 +904,7 @@ package check_postgres;
                 $name = "dbname$1";
             }
             elsif ($name =~ /^u(\d+)$/o) {
    -            $name = 'dbuser$1';
    +            $name = "dbuser$1";
             }
     
             ## These options are multiples ('@s')
    @@ -1634,7 +1634,7 @@ sub finishup {
                     or ($DEBUGOUTPUT =~ /u/io and $type eq 'u');
             }
             for (sort keys %$info) {
    -            printf "%s %s%s ",
    +            printf '%s %s%s ',
                     $_,
                     $showdebug ? "[DEBUG: $DEBUG_INFO] " : '',
                     join $SEP => map { $_->[0] } @{$info->{$_}};
    @@ -2414,31 +2414,31 @@ sub run_command {
     
                 ## Transform psql output into an arrayref of hashes
                 my @stuff;
    -            my $num = 0;
    +            my $lnum = 0;
                 my $lastval;
                 for my $line (split /\n/ => $db->{slurp}) {
     
                     if (index($line,'-')==0) {
    -                    $num++;
    +                    $lnum++;
                         next;
                     }
                     if ($line =~ /^([\?\w]+)\s+\| (.*)/) {
    -                    $stuff[$num]{$1} = $2;
    +                    $stuff[$lnum]{$1} = $2;
                         $lastval = $1;
                     }
                     elsif ($line =~ /^QUERY PLAN\s+\| (.*)/) {
    -                    $stuff[$num]{queryplan} = $1;
    +                    $stuff[$lnum]{queryplan} = $1;
                         $lastval = 'queryplan';
                     }
                     elsif ($line =~ /^\s+: (.*)/) {
    -                    $stuff[$num]{$lastval} .= "\n$1";
    +                    $stuff[$lnum]{$lastval} .= "\n$1";
                     }
                     elsif ($line =~ /^\s+\| (.+)/) {
    -                    $stuff[$num]{$lastval} .= "\n$1";
    +                    $stuff[$lnum]{$lastval} .= "\n$1";
                     }
                     ## No content: can happen in the source of functions, for example
                     elsif ($line =~ /^\s+\|\s+$/) {
    -                    $stuff[$num]{$lastval} .= "\n";
    +                    $stuff[$lnum]{$lastval} .= "\n";
                     }
                     else {
                         my $msg = msg('no-parse-psql');
    @@ -2457,8 +2457,8 @@ sub run_command {
                         if (! $opt{stop_looping}) {
                             ## Just in case...
                             $opt{stop_looping} = 1;
    -                        my $info = run_command('SELECT version() AS version');
    -                        (my $v = $info->{db}[0]{slurp}[0]{version}) =~ s/(\w+ \S+).+/$1/;
    +                        my $linfo = run_command('SELECT version() AS version');
    +                        (my $v = $linfo->{db}[0]{slurp}[0]{version}) =~ s/(\w+ \S+).+/$1/;
                             warn "Postgres version: $v\n";
                         }
                         exit 1;
    @@ -4710,7 +4710,7 @@ sub check_hot_standby_delay {
         if (1 == $slave) {
             ($slave, $master) = (2, 1);
             for my $k (qw(host port dbname dbuser dbpass)) {
    -            ($opt{$k}, $opt{$k . 2}) = ($opt{$k . 2}, $opt{$k});
    +            ($opt{$k}, $opt{$k . 2}) = ($opt{$k . 2}, $opt{$k}); ## no critic (ProhibitMismatchedOperators)
             }
         }
     
    @@ -4903,7 +4903,7 @@ sub check_last_vacuum_analyze {
                 add_unknown (
                     $found ? $type eq 'vacuum' ? msg('vac-nomatch-v')
                     : msg('vac-nomatch-a')
    -                : msg('no-match-table')
    +                : msg('no-match-table') ## no critic (RequireTrailingCommaAtNewline)
                 );
             }
             elsif ($maxtime < 0) {
    @@ -5536,7 +5536,7 @@ sub check_pgbouncer_backends {
         }
     
         ## Grab information from the config
    -    $SQL = qq{SHOW CONFIG};
    +    $SQL = 'SHOW CONFIG';
     
         my $info = run_command($SQL, { regex => qr{\d+}, emptyok => 1 } );
     
    @@ -5552,7 +5552,7 @@ sub check_pgbouncer_backends {
         }
     
         ## Grab information from pools
    -    $SQL = qq{SHOW POOLS};
    +    $SQL = 'SHOW POOLS';
     
         $info = run_command($SQL, { regex => qr{\d+}, emptyok => 1 } );
     
    @@ -5897,7 +5897,7 @@ sub check_relation_size {
     
                 my $nicename = $kind eq 'r' ? "$schema.$name" : $name;
     
    -            $db->{perf} .= sprintf "%s%s=%sB;%s;%s",
    +            $db->{perf} .= sprintf '%s%s=%sB;%s;%s',
                     $VERBOSE==1 ? "\n" : ' ',
                     perfname($nicename), $size, $warning, $critical;
                 ($max=$size, $pmax=$psize, $kmax=$kind, $nmax=$name, $smax=$schema) if $size > $max;
    @@ -6479,13 +6479,13 @@ sub check_same_schema {
                             }
     
                             if (exists $tdiff->{list}{$col}{exists}) {
    -                            my $e = $tdiff->{list}{$col}{exists};
    -                            for my $name (sort keys %$e) {
    +                            my $ex = $tdiff->{list}{$col}{exists};
    +                            for my $name (sort keys %$ex) {
                                     push @msg => sprintf qq{  "%s":\n    %s\n},
                                         $col,
                                         msg('ss-notset', $name);
    -                                my $isthere = join ', ' => sort { $a<=>$b } keys %{ $e->{$name}{isthere} };
    -                                my $nothere = join ', ' => sort { $a<=>$b } keys %{ $e->{$name}{nothere} };
    +                                my $isthere = join ', ' => sort { $a<=>$b } keys %{ $ex->{$name}{isthere} };
    +                                my $nothere = join ', ' => sort { $a<=>$b } keys %{ $ex->{$name}{nothere} };
                                     push @msg => sprintf "      %-*s %s\n      %-*s %s\n",
                                         $maxsize, $msg_exists,
                                         $isthere,
    @@ -6661,7 +6661,7 @@ sub read_audit_file {
         close $fh or warn qq{Could not close "$filename": $!\n};
     
         my $POSTGRES1;
    -    eval $data;
    +    eval $data; ## no critic (ProhibitStringyEval)
         if ($@) {
             die qq{Failed to parse file "$filename": $@\n};
         }
    @@ -7000,6 +7000,7 @@ sub check_sequence {
         (my $c = $critical) =~ s/\D//;
     
         ## Gather up all sequence names
    +    ## no critic
         my $SQL = q{
     SELECT DISTINCT ON (nspname, seqname) nspname, seqname,
       quote_ident(nspname) || '.' || quote_ident(seqname) AS safename, typname
    @@ -7040,6 +7041,7 @@ sub check_sequence {
     ) AS seqs
     ORDER BY nspname, seqname, typname
     };
    +    ## use critic
     
         my $info = run_command($SQL, {regex => qr{\w}, emptyok => 1} );
     
    @@ -7222,7 +7224,7 @@ sub check_slony_status {
         }
     
         my $SLSQL =
    -qq{SELECT
    +q{SELECT
      ROUND(EXTRACT(epoch FROM st_lag_time)) AS lagtime,
      st_origin,
      st_received,
    @@ -7363,19 +7365,19 @@ sub check_txn_idle {
     
         ## We don't GROUP BY because we want details on every connection
         ## Someday we may even break things down by database
    -    if ($type ne "qtime") {
    +    if ($type ne 'qtime') {
             $SQL = q{SELECT datname, datid, procpid, usename, client_addr, xact_start, current_query, }.
                 q{CASE WHEN client_port < 0 THEN 0 ELSE client_port END AS client_port, }.
                 qq{COALESCE(ROUND(EXTRACT(epoch FROM now()-$start)),0) AS seconds }.
                 qq{FROM pg_stat_activity WHERE $clause$USERWHERECLAUSE }.
    -            qq{ORDER BY xact_start, query_start, procpid DESC};
    +            q{ORDER BY xact_start, query_start, procpid DESC};
         }
         else {
             $SQL = q{SELECT datname, datid, procpid, usename, client_addr, current_query, }.
                 q{CASE WHEN client_port < 0 THEN 0 ELSE client_port END AS client_port, }.
                 qq{COALESCE(ROUND(EXTRACT(epoch FROM now()-$start)),0) AS seconds }.
                 qq{FROM pg_stat_activity WHERE $clause$USERWHERECLAUSE }.
    -            qq{ORDER BY query_start, procpid DESC};
    +            q{ORDER BY query_start, procpid DESC};
         }
     
         my $info = run_command($SQL, { emptyok => 1 } );
    @@ -7391,7 +7393,7 @@ sub check_txn_idle {
         my $count = 0;
     
         ## Info about the top offender
    -    my $whodunit = "";
    +    my $whodunit = '';
         if ($MRTG) {
             if (defined $db->{dbname}) {
                 $whodunit = "DB: $db->{dbname}";
    @@ -7422,7 +7424,7 @@ sub check_txn_idle {
             }
     
             ## Detect other cases where pg_stat_activity is not fully populated
    -        if ($type ne "qtime" and length $r->{xact_start} and $r->{xact_start} !~ /\d/o) {
    +        if ($type ne 'qtime' and length $r->{xact_start} and $r->{xact_start} !~ /\d/o) {
                 add_unknown msg('psa-noexact');
                 return;
             }
    diff --git a/perlcriticrc b/perlcriticrc
    index b7579658..980df99a 100644
    --- a/perlcriticrc
    +++ b/perlcriticrc
    @@ -4,15 +4,13 @@ verbose = 8
     profile-strictness = quiet
     
     [Documentation::PodSpelling]
    -stop_words = Mullane Nagios Slony Slony's nols salesrep psql dbname postgres USERNAME usernames dbuser pgpass nagios stderr showperf symlinked timesync criticals quirm lancre exabytes sami includeuser excludeuser flagg tardis WAL tablespaces tablespace perflimit burrick mallory grimm oskar ExclusiveLock garrett artemus queryname speedtest checksum checksums morpork klatch pluto faceoff slon greg watson franklin wilkins scott Sabino Seklecki dbpass autovacuum Astill refactoring NAGIOS localhost cronjob symlink symlinks backends snazzo logfile syslog parens plugin Cwd Ioannis Tambouras schemas SQL MRTG mrtg uptime datallowconn dbhost dbport ok contrib pageslots robert dylan emma fsm minvalue nextval dbstats del ret upd Bucardo noidle bucardo petabytes zettabytes tuples noobjectnames noposition nofuncbody slony noperms nolanguage battlestar pgbouncer pgBouncer
    -
    -
    -
    +stop_words = Mullane Nagios Slony Slony's nols salesrep psql dbname postgres USERNAME usernames dbuser pgpass nagios stderr showperf symlinked timesync criticals quirm lancre exabytes sami includeuser excludeuser flagg tardis WAL tablespaces tablespace perflimit burrick mallory grimm oskar ExclusiveLock garrett artemus queryname speedtest checksum checksums morpork klatch pluto faceoff slon greg watson franklin wilkins scott Sabino Seklecki dbpass autovacuum Astill refactoring NAGIOS localhost cronjob symlink symlinks backends snazzo logfile syslog parens plugin Cwd Ioannis Tambouras schemas SQL MRTG mrtg uptime datallowconn dbhost dbport ok contrib pageslots robert dylan emma fsm minvalue nextval dbstats del ret upd Bucardo noidle bucardo petabytes zettabytes tuples noobjectnames noposition nofuncbody slony noperms nolanguage battlestar pgbouncer pgBouncer datadir wget PostgreSQL commitratio idxscan idxtupread idxtupfetch idxblksread idxblkshit seqscan seqtupread hitratio xlog boxinfo pgbouncer's login maxwait noname noschema noperm filenames GSM
     
     [-Bangs::ProhibitFlagComments]
     [-Bangs::ProhibitNumberedNames]
     [-Bangs::ProhibitVagueNames]
     
    +[-BuiltinFunctions::ProhibitBooleanGrep]
     [-BuiltinFunctions::ProhibitComplexMappings]
     [-BuiltinFunctions::ProhibitReverseSortBlock]
     
    @@ -22,6 +20,8 @@ stop_words = Mullane Nagios Slony Slony's nols salesrep psql dbname postgres USE
     [-CodeLayout::RequireTidyCode]
     [-CodeLayout::RequireUseUTF8]
     
    +[-Compatibility::PodMinimumVersion]
    +
     [-ControlStructures::ProhibitCascadingIfElse]
     [-ControlStructures::ProhibitDeepNests]
     [-ControlStructures::ProhibitMutatingListFunctions]
    @@ -79,6 +79,7 @@ stop_words = Mullane Nagios Slony Slony's nols salesrep psql dbname postgres USE
     [-Tics::ProhibitLongLines]
     
     [-ValuesAndExpressions::ProhibitAccessOfPrivateData]
    +[-ValuesAndExpressions::ProhibitCommaSeparatedStatements]
     [-ValuesAndExpressions::ProhibitEmptyQuotes]
     [-ValuesAndExpressions::ProhibitImplicitNewlines]
     [-ValuesAndExpressions::ProhibitMagicNumbers]
    @@ -86,11 +87,14 @@ stop_words = Mullane Nagios Slony Slony's nols salesrep psql dbname postgres USE
     [-ValuesAndExpressions::ProhibitNoisyQuotes]
     [-ValuesAndExpressions::ProhibitVersionStrings]
     [-ValuesAndExpressions::RequireNumberSeparators]
    +[-ValuesAndExpressions::RequireNumericVersion]
     [-ValuesAndExpressions::RestrictLongStrings]
     
    +[-Variables::ProhibitLocalVars]
     [-Variables::ProhibitPackageVars]
     [-Variables::ProhibitPunctuationVars]
     [-Variables::ProhibitUselessInitialization]
     [-Variables::RequireInitializationForLocalVars]
     [-Variables::RequireLexicalLoopIterators]
     [-Variables::RequireLocalizedPunctuationVars]
    +
    diff --git a/t/00_release.t b/t/00_release.t
    index 82f31610..36604b70 100644
    --- a/t/00_release.t
    +++ b/t/00_release.t
    @@ -111,11 +111,9 @@ for my $mfile (@mfiles) {
     	file_is_clean($mfile);
     }
     
    -exit;
    -
     sub file_is_clean {
     
    -	my $file = shift or die;
    +	my $file = shift or die; ## no critic (ProhibitReusedNames)
     
     	if (!open $fh, '<', $file) {
     		fail qq{Could not open "$file": $!\n};
    diff --git a/t/02_custom_query.t b/t/02_custom_query.t
    index 276f62da..a6b2d4fb 100644
    --- a/t/02_custom_query.t
    +++ b/t/02_custom_query.t
    @@ -40,7 +40,7 @@ like ($cp->run(qq{--query="$good_query" --valtype=string --warning=abc}),
           qr{$label OK}, $t);
     
     $t = qq{$S handles 'string' type for match};
    -like ($cp->run(qq{--query="SELECT 'abc' AS result" --valtype=string --warning=abc}),
    +like ($cp->run(q{--query="SELECT 'abc' AS result" --valtype=string --warning=abc}),
           qr{$label WARNING}, $t);
     
     $t = qq{$S handles 'time' type};
    diff --git a/t/02_same_schema.t b/t/02_same_schema.t
    index 3a205c79..ec70f5f6 100644
    --- a/t/02_same_schema.t
    +++ b/t/02_same_schema.t
    @@ -224,7 +224,7 @@ Schema "schema_a":
     
     $t = qq{$S reports when schemas have different acls};
     $dbh1->do(q{ALTER SCHEMA schema_a OWNER TO check_postgres_testing});
    -$dbh1->do(qq{GRANT USAGE ON SCHEMA schema_a TO check_postgres_testing});
    +$dbh1->do(q{GRANT USAGE ON SCHEMA schema_a TO check_postgres_testing});
     like ($cp1->run($connect2),
           qr{^$label CRITICAL.*Items not matched: 1 .*
     Schema "schema_a":
    @@ -287,7 +287,7 @@ Table "public.berri":
     $dbh1->do(q{ALTER TABLE berri SET WITHOUT OIDS});
     
     $t = qq{$S reports simple table acl differences};
    -$dbh1->do(qq{GRANT SELECT ON TABLE berri TO alternate_owner});
    +$dbh1->do(q{GRANT SELECT ON TABLE berri TO alternate_owner});
     ## No anchoring here as check_postgres_testing implicit perms are set too!
     like ($cp1->run($connect2),
           qr{^$label CRITICAL.*Items not matched: 1 .*
    @@ -299,7 +299,7 @@ Table "public.berri":
           $t);
     
     $t = qq{$S reports complex table acl differences};
    -$dbh2->do(qq{GRANT UPDATE,DELETE ON TABLE berri TO alternate_owner});
    +$dbh2->do(q{GRANT UPDATE,DELETE ON TABLE berri TO alternate_owner});
     like ($cp1->run($connect2),
           qr{^$label CRITICAL.*Items not matched: 1 .*
     Table "public.berri":
    diff --git a/t/02_settings_checksum.t b/t/02_settings_checksum.t
    index a5649754..a4df6b30 100644
    --- a/t/02_settings_checksum.t
    +++ b/t/02_settings_checksum.t
    @@ -53,7 +53,7 @@ $t = qq{$S accepts matching checksum};
     like ($cp->run("-w $true_checksum"), qr/OK.*\Qchecksum: $true_checksum\E/, $t);
     
     $t=qq{$S returns the expected output for MRTG(failure)};
    -like ($cp->run(qq{--mrtg 123 --output=MRTG}),
    +like ($cp->run(q{--mrtg 123 --output=MRTG}),
           qr{^0\n0\n\n\d+}, $t);
     
     $t=qq{$S returns the expected output for MRTG(success)};
    diff --git a/t/CP_Testing.pm b/t/CP_Testing.pm
    index 05d6a1bf..6279322f 100644
    --- a/t/CP_Testing.pm
    +++ b/t/CP_Testing.pm
    @@ -229,7 +229,7 @@ sub test_database_handle {
                 if ($res !~ /$newuser/) {
                     $COM = qq{psql -d template1 -q -h "$host" -c "CREATE USER $newuser"};
                     system $COM;
    -                $SQL = q{UPDATE pg_shadow SET usesuper='t' WHERE usename = '$newuser'};
    +                $SQL = qq{UPDATE pg_shadow SET usesuper='t' WHERE usename = '$newuser'};
                     $COM = qq{psql -d postgres -q -h "$host" -c "$SQL"};
                     system $COM;
                 }
    @@ -240,7 +240,7 @@ sub test_database_handle {
                 if ($res !~ /$newuser/) {
                     $COM = qq{psql -d template1 -q -h "$host" -c "CREATE USER $newuser"};
                     system $COM;
    -                $SQL = q{UPDATE pg_shadow SET usesuper='t' WHERE usename = '$newuser'};
    +                $SQL = qq{UPDATE pg_shadow SET usesuper='t' WHERE usename = '$newuser'};
                     $COM = qq{psql -d postgres -q -h "$host" -c "$SQL"};
                     system $COM;
                 }
    
    From fb775d26f10b7fff15ca91827d28dcebc3b5f46e Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Wed, 18 Jan 2012 10:56:22 +0800
    Subject: [PATCH 33/42] Ready for 2.19.0 release
    
    ---
     SIGNATURE              | 41 +++++++++++++++++++++--------------------
     check_postgres.pl      |  2 +-
     check_postgres.pl.asc  |  6 +++---
     check_postgres.pl.html |  2 +-
     4 files changed, 26 insertions(+), 25 deletions(-)
    
    diff --git a/SIGNATURE b/SIGNATURE
    index 8010892d..0cf82b61 100644
    --- a/SIGNATURE
    +++ b/SIGNATURE
    @@ -1,5 +1,5 @@
     This file contains message digests of all files listed in MANIFEST,
    -signed via the Module::Signature module, version 0.66.
    +signed via the Module::Signature module, version 0.68.
     
     To verify the content in this distribution, first make sure you have
     Module::Signature installed, then type:
    @@ -14,25 +14,26 @@ not run its Makefile.PL or Build.PL.
     -----BEGIN PGP SIGNED MESSAGE-----
     Hash: RIPEMD160
     
    -SHA1 1a85225b9dc18ad9ae156a87dbecefe906688b7a MANIFEST
    +SHA1 9ab773a8191ac2df4439c8bbcc99dba35d025883 MANIFEST
     SHA1 92f9e28d28d95763cce24d588b19262efc7218f7 MANIFEST.SKIP
    -SHA1 0fad21fffc4da972a3678b914dd4c17c725d12b9 META.yml
    -SHA1 e47bcde5ecf9db177398ba338817d5df6c450e8d Makefile.PL
    -SHA1 700897deb28bd8f514817db6c0eb238efb61a7f1 README
    +SHA1 4af2c5cd509eb4e60c5aaeea624a1d59f0cba745 META.yml
    +SHA1 f96da4b33e66d585d6cffa0d39205c53dc966a70 Makefile.PL
    +SHA1 acffbf8ac9243e22197a07cb02fb1dd79c553881 README
     SHA1 3bdea49b9baf59b6c2f1c238f45794ba0f3fdd0f TODO
    -SHA1 0c7d027d2d83e346741b6413b2f1be61e1041dc3 check_postgres.pl
    -SHA1 a688d42b11c0bef9f46d002bbaebe30ce13919a7 check_postgres.pl.asc
    -SHA1 8b68cdd1a336b138050fef8d287cfd684a5f7f2c check_postgres.pl.html
    -SHA1 77556e0d493cf22602fff7837cf80832317e498f perlcriticrc
    +SHA1 df5500fe85ffaa96428c755ccdccd38ab275ebb8 check_postgres.pl
    +SHA1 a46c77b4be9458ced64673686f27d9194ce0e7ed check_postgres.pl.asc
    +SHA1 082cf28c0de8db75ce0a5bd3e8dbfebbe7abb8a1 check_postgres.pl.html
    +SHA1 2a5730008e80e9c94a3a31991203b19fd6c41cad perlcriticrc
     SHA1 ef43082a685d993fdd151de16590ce0f6832de7a t/00_basic.t
     SHA1 29700e8331d1780e87b858581054cd190e4f4ecb t/00_signature.t
     SHA1 439053254ee01e2ec406f9d1605dc5e28257b8bd t/00_test_tester.t
     SHA1 9e49f1a4de88e64ba73b3cbcf45cba158ca49afc t/02_autovac_freeze.t
    -SHA1 a53671892d1ff8ee39134a1bbaa31064ada296e0 t/02_backends.t
    +SHA1 fc83c41652b0cef2dc07efdea30400a747a27cf1 t/02_backends.t
     SHA1 923acca525a528ccefd630eef8e015007a1bc5d0 t/02_bloat.t
    -SHA1 a0dd2dde7ea934335b61de6c4335768fc372bfbe t/02_checkpoint.t
    +SHA1 58f04f98539371d9469ca93890b3f61a990fa343 t/02_checkpoint.t
    +SHA1 c3e31bedea2a55b49d61874a7e4b8f6900746b22 t/02_cluster_id.t
     SHA1 4c403c8d733fff18e8ef5b198c0f0837419b4e77 t/02_connection.t
    -SHA1 59fb92cebb81fe2e5a46cde2b0e0b9420728ba3a t/02_custom_query.t
    +SHA1 3ec5348a4125429a16e486a3850baa43954d278a t/02_custom_query.t
     SHA1 6e255ba83d65c41c9f27ec05b3c66b57f531b42e t/02_database_size.t
     SHA1 4d5d6b521ae8ec45cb14feea155858379ec77028 t/02_dbstats.t
     SHA1 f01542845070822b80cac7aaa3038eae50f8d3ae t/02_disabled_triggers.t
    @@ -43,7 +44,7 @@ SHA1 f83838ef9da1d67e026f88b833522a73f3ae6699 t/02_last_analyze.t
     SHA1 d6a7fba8f0e1fd4f3ad1f3c01a05d12f2e35e64c t/02_last_vacuum.t
     SHA1 5fca9f38305fd0c8c5d1726d08f0a95ae8755b8e t/02_listener.t
     SHA1 87d175a8969b06c549ce0757995cf98a42fe3311 t/02_locks.t
    -SHA1 951b8b74b818554be71e089a0ddd5f6063a07c33 t/02_logfile.t
    +SHA1 a780920848536059af81bc77140ed70051630d00 t/02_logfile.t
     SHA1 2c31b39e6005c7e9ae5060ea42de549de895b39f t/02_new_version_bc.t
     SHA1 f0d114dfc2f1149ca29c249d3c9b72c7c5e3ba92 t/02_new_version_cp.t
     SHA1 1381613f67c93854c9f8b73a3b168348bdd56af3 t/02_new_version_pg.t
    @@ -53,9 +54,9 @@ SHA1 2706f51b92149330f123e174ad009ada0124a538 t/02_query_runtime.t
     SHA1 033bb1162ad990161da1c591d5fb9f7c452ee4c9 t/02_query_time.t
     SHA1 bdd9a4a73bbce6a5450cbc04e1fe357f3bc587a7 t/02_relation_size.t
     SHA1 0c6cb335db415dd354ac814a88424f01af57ff31 t/02_replicate_row.t
    -SHA1 59fb6249b2dd48235a9d85372d2df764f0efed75 t/02_same_schema.t
    +SHA1 e36d0632a32b22ebdded6ab91fd46aca7f8b2b31 t/02_same_schema.t
     SHA1 130fee186667da0991a230dbc999d6fc104d1ebf t/02_sequence.t
    -SHA1 f498f14c7b05792e18b99ef7d6c91592682d29b6 t/02_settings_checksum.t
    +SHA1 0474d2d059dff8638f62b739aa80713f56308d62 t/02_settings_checksum.t
     SHA1 1f3cfd12a21870c5e4615fb4eff012085e30182f t/02_slony_status.t
     SHA1 64493100381abd82aa1eb06a46d67456f4e8486d t/02_timesync.t
     SHA1 221d3c78eece2a5fc796611e3133e5ccc8f8fad0 t/02_txn_idle.t
    @@ -63,13 +64,13 @@ SHA1 7c77be0301c936974778c7c92186088ef9b06526 t/02_txn_time.t
     SHA1 24ff2b5b0690557e1a45227d5c1131226c9ff30a t/02_txn_wraparound.t
     SHA1 2270e466a5761256be6b69cc0c7e8c03f2414e3b t/02_version.t
     SHA1 93c5da727c39f3dbb1953d061fa6f96578ba7952 t/02_wal_files.t
    -SHA1 4b0eb2dcbe27f5d377d1701148bc58a25f06a40c t/03_translations.t
    +SHA1 60b209d285ddd9a44a55751dffb6e8a927b27337 t/03_translations.t
     SHA1 eb66336f915f77a1cd82c1b19b44acc7dc2d5038 t/04_timeout.t
     SHA1 96e6e5da3e1f6753a469e7afc8cf070024b33b23 t/99_cleanup.t
    -SHA1 902dc689577e54b5de30b8f484847827002afd07 t/CP_Testing.pm
    +SHA1 d2021f28db03e69e8cfdca8760ad032abf9357ae t/CP_Testing.pm
     -----BEGIN PGP SIGNATURE-----
     
    -iEYEAREDAAYFAk6InpMACgkQvJuQZxSWSsjpzACffRDnggz9RE+Ldej4q6cuv2hv
    -GzwAoIlMdReFt6I49aWkeUmNd3DSYobp
    -=SiEv
    +iEYEAREDAAYFAk8WNKQACgkQvJuQZxSWSsj/oACaAkJNba/iUhZkTwAsdbHQkx/c
    +Vt0AoNvyFLULIolnmD/cpSCTZ3diyxX7
    +=rOic
     -----END PGP SIGNATURE-----
    diff --git a/check_postgres.pl b/check_postgres.pl
    index c546c99e..22f3b440 100755
    --- a/check_postgres.pl
    +++ b/check_postgres.pl
    @@ -9519,7 +9519,7 @@ =head1 HISTORY
     
     =over 4
     
    -=item B
    +=item B January 17, 2012
     
       Add the --assume-prod option (Cédric Villemain)
     
    diff --git a/check_postgres.pl.asc b/check_postgres.pl.asc
    index 6a7d2205..e5e7b91d 100644
    --- a/check_postgres.pl.asc
    +++ b/check_postgres.pl.asc
    @@ -1,6 +1,6 @@
     -----BEGIN PGP SIGNATURE-----
     
    -iEYEABEDAAYFAk6InwgACgkQvJuQZxSWSsgdkQCg6oV+Z8g2Ukpl5P/5irOzOI1Q
    -cF4An3WGHLVbGA6eo86Qz0EjGOQ5WUZ+
    -=dtwa
    +iEYEABEDAAYFAk8WNKAACgkQvJuQZxSWSsj8AgCg1+H5xOi5uiSDUmzwfpW5wb0b
    +4Y4An0eWHKQRtG/NWYoZyBH0cE55R76u
    +=oeHj
     -----END PGP SIGNATURE-----
    diff --git a/check_postgres.pl.html b/check_postgres.pl.html
    index a9996e7e..3ffef636 100644
    --- a/check_postgres.pl.html
    +++ b/check_postgres.pl.html
    @@ -1754,7 +1754,7 @@ 

    MAILING LIST

    HISTORY

    Items not specifically attributed are by GSM (Greg Sabino Mullane).

    -
    Version 2.19.0
    +
    Version 2.19.0 January 17, 2012
    
    From 4a2c60d3001456858b719c2e69b9975def34f58f Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Wed, 18 Jan 2012 10:57:36 +0800
    Subject: [PATCH 34/42] Note need to commit before the tagging.
    
    ---
     README.dev | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/README.dev b/README.dev
    index eb482bd8..65d349d5 100644
    --- a/README.dev
    +++ b/README.dev
    @@ -13,6 +13,7 @@ Quick notes on the current release process:
     * Run: perl Makefile.PL; make html
     * Run: make signature_asc
     * Run: make signature
    +* Run: git commit -a
     * Add a new tag: git tag -u 14964ac8 1.2.3 -m "Version 1.2.3, released August 3, 2009" 
     * Run: export TEST_SIGNATURE=1 TEST_CRITIC=1 TEST_SPELL=1 TEST_POD=1 TEST_AUTHOR=1
     * Run: make distclean; perl Makefile.PL; make disttest
    
    From 685049ca10242fb0e351dadb9b0ee520d19c74fb Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Wed, 18 Jan 2012 11:37:17 +0800
    Subject: [PATCH 35/42] More tweaks to the release process.
    
    ---
     README.dev | 14 +++++++++++---
     1 file changed, 11 insertions(+), 3 deletions(-)
    
    diff --git a/README.dev b/README.dev
    index 65d349d5..83bf2a89 100644
    --- a/README.dev
    +++ b/README.dev
    @@ -28,15 +28,23 @@ Login to the bucardo.org box, and then:
     * git pull
     * make distclean; perl Makefile.PL; make disttest; make dist
     * prove -v t/00_release.t
    -* cd ~/htdocs/check_postgres
    +* cd ~/www/downloads
     * cp -i ~/code/check_postgres/check_postgres* .
    +* cd ~/www/check_postgres
    +* ln -s ../downloads/ .
     * edit latest_version.txt
     * edit index.html
     
    +* Edit the bucardo.org page and bump the version: http://bucardo.org/wiki/Check_postgres
    +
     * Email to check_postgres-announce with summary of changes
     
    +* Email the Postgres Weekly News
    +
    +* Email pgsql-announce if this is a major version
    +
     Once the new version is out there:
     
    -* Make sure the new version is in the pulldown list of available versions.
    -* Go through and make sure all bugs solved in this release are marked as resolved
    +* Make sure the new version is in the pulldown list of available versions on bugzilla.
    +* Go through and make sure all bugs solved in this release are marked as resolved.
     
    
    From dd6d736a1a0ee075b3e2ebec1e30cb761127fe48 Mon Sep 17 00:00:00 2001
    From: Greg Sabino Mullane 
    Date: Thu, 19 Jan 2012 00:23:16 +0800
    Subject: [PATCH 36/42] Add link
    
    ---
     README.dev | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/README.dev b/README.dev
    index 83bf2a89..e27e24e2 100644
    --- a/README.dev
    +++ b/README.dev
    @@ -46,5 +46,6 @@ Login to the bucardo.org box, and then:
     Once the new version is out there:
     
     * Make sure the new version is in the pulldown list of available versions on bugzilla.
    +** http://bucardo.org/bugzilla/editversions.cgi
     * Go through and make sure all bugs solved in this release are marked as resolved.
     
    
    From d276aec9c864e874296a21379ffd9d91d00d50e3 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?C=C3=A9dric=20Villemain?= 
    Date: Sun, 22 Jan 2012 20:46:43 +0800
    Subject: [PATCH 37/42] Add `pgagent_jobs` test.
    
    From: "David E. Wheeler" 
    
    This patch adds support for checking for failed pgAgent jobs within a specified
    period of time. You can specify either --critical or --warning as a period of
    time, and it will report on failures within that period of time previous to the
    current time. Job failures are determined by a non-0 status in a job step
    record.
    
    Using this test obviously requiers that the pgAgent schema be installed. I've
    also included a bunch of unit tests to make sure it works the way I would expect
    (the test will create a schema for testing) and documentation.
    
    As part of this, I've introduced the `any_warning` argument to
    `validate_range()`. The `pgagent_jobs` test does not care if you specify a
    warning value greater than the critical value (indeed, I expect that if one used
    both at all, the warning would be much longer). So this new argument prevents
    the `range-warnbigtime` or `range-warnbigsize` failures from being triggered.
    
    Cedric: I sorted the POD and added the action_info so that t/05_docs.t is ok.
    I also built and push the new .html
    ---
     check_postgres.pl      | 102 ++++++++++++++++-
     check_postgres.pl.html |  22 ++++
     t/02_pgagent_jobs.t    | 242 +++++++++++++++++++++++++++++++++++++++++
     3 files changed, 363 insertions(+), 3 deletions(-)
     create mode 100644 t/02_pgagent_jobs.t
    
    diff --git a/check_postgres.pl b/check_postgres.pl
    index 22f3b440..93a7751f 100755
    --- a/check_postgres.pl
    +++ b/check_postgres.pl
    @@ -189,6 +189,7 @@ package check_postgres;
         'opt-psql-nofind'    => q{Could not find a suitable psql executable},
         'opt-psql-nover'     => q{Could not determine psql version},
         'opt-psql-restrict'  => q{Cannot use the --PSQL option when NO_PSQL_OPTION is on},
    +    'pgagent-jobs-ok'    => q{No failed jobs},
         'pgbouncer-pool'     => q{Pool=$1 $2=$3},
         'pgb-backends-mrtg'  => q{DB=$1 Max connections=$2},
         'pgb-backends-msg'   => q{$1 of $2 connections ($3%)},
    @@ -1160,6 +1161,7 @@ package check_postgres;
      pgb_pool_maxwait    => [1, 'Check the current maximum wait time for client connections in pgbouncer pools.'],
      pgbouncer_backends  => [0, 'Check how many clients are connected to pgbouncer compared to max_client_conn.'],
      pgbouncer_checksum  => [0, 'Check that no pgbouncer settings have changed since the last check.'],
    + pgagent_jobs        => [0, 'Check for no failed pgAgent jobs within a specified period of time.'],
      prepared_txns       => [1, 'Checks number and age of prepared transactions.'],
      query_runtime       => [0, 'Check how long a specific query takes to run.'],
      query_time          => [1, 'Checks the maximum running time of current queries.'],
    @@ -1985,6 +1987,8 @@ sub finishup {
     ## Check how many clients are connected to pgbouncer compared to max_client_conn.
     check_pgbouncer_backends() if $action eq 'pgbouncer_backends';
     
    +check_pgagent_jobs() if $action eq 'pgagent_jobs';
    +
     ##
     ## Everything past here does not hit a Postgres database
     ##
    @@ -2826,7 +2830,7 @@ sub validate_range {
                     ndie msg('range-seconds', 'critical')
                 }
                 $critical = $1;
    -            if (length $warning and $warning > $critical) {
    +            if (!$arg->{any_warning} and length $warning and $warning > $critical) {
                     ndie msg('range-warnbigtime', $warning, $critical);
                 }
             }
    @@ -2837,7 +2841,7 @@ sub validate_range {
             if (! length $critical and ! length $warning) {
                 ndie msg('range-notime');
             }
    -        if (length $warning and length $critical and $warning > $critical) {
    +        if (!$arg->{any_warning} and length $warning and length $critical and $warning > $critical) {
                 ndie msg('range-warnbigtime', $warning, $critical);
             }
         }
    @@ -2865,7 +2869,7 @@ sub validate_range {
                     ndie msg('range-badsize', 'warning');
                 }
                 $warning = size_in_bytes($1,$2);
    -            if (length $critical and $warning > $critical) {
    +            if (!$arg->{any_warning} and length $critical and $warning > $critical) {
                     ndie msg('range-warnbigsize', $warning, $critical);
                 }
             }
    @@ -5429,6 +5433,73 @@ sub check_new_version_tnm {
     } ## end of check_new_version_tnm
     
     
    +sub check_pgagent_jobs {
    +    ## Check for failed pgAgent jobs.
    +    ## Supports: Nagios
    +    ## Critical and warning are intervals.
    +    ## Example: --critical="1 hour"
    +    ## Example: --warning="2 hours"
    +
    +    my ($warning, $critical) = validate_range({ type => 'time', any_warning => 1 });
    +
    +    # Determine critcal warning column contents.
    +    my $is_crit = $critical && $warning
    +        ? "GREATEST($critical - EXTRACT('epoch' FROM NOW() - (jlog.jlgstart + jlog.jlgduration)), 0)"
    +        : $critical ? 1 : 0;
    +
    +    # Determine max time to examine.
    +    my $seconds = do {
    +        no warnings;
    +        $warning > $critical ? $warning : $critical;
    +    };
    +
    +    $SQL = qq{
    +        SELECT jlog.jlgid
    +             , job.jobname
    +             , step.jstname
    +             , slog.jslresult
    +             , slog.jsloutput
    +             , $is_crit AS critical
    +          FROM pgagent.pga_job job
    +          JOIN pgagent.pga_joblog     jlog ON job.jobid  = jlog.jlgjobid
    +          JOIN pgagent.pga_jobstep    step ON job.jobid  = step.jstjobid
    +          JOIN pgagent.pga_jobsteplog slog ON jlog.jlgid = slog.jsljlgid AND step.jstid = slog.jsljstid
    +         WHERE slog.jslresult <> 0
    +           AND EXTRACT('epoch' FROM NOW() - (jlog.jlgstart + jlog.jlgduration)) < $seconds
    +    };
    +
    +    my $info = run_command($SQL);
    +
    +    for $db (@{$info->{db}}) {
    +        my @rows = @{ $db->{slurp} } or do {
    +            add_ok msg('pgagent-jobs-ok');
    +            next;
    +        };
    +
    +        if ($rows[0]{critical} !~ /^(?:[01]|\d+[.]\d+)$/) {
    +            add_unknown msg('invalid-query', $db->{slurp});
    +            next;
    +        }
    +
    +        my ($is_crit, @msg);
    +        my $log_id = -1;
    +        for my $step (@rows) {
    +            my $output = $step->{jsloutput} || '(NO OUTPUT)';
    +            push @msg => "$step->{jslresult} $step->{jobname}/$step->{jstname}: $output";
    +            $is_crit ||= $step->{critical};
    +        }
    +
    +        (my $msg = join '; ' => @msg) =~ s{\r?\n}{ }g;
    +        if ($is_crit) {
    +            add_critical $msg;
    +        } else {
    +            add_warning $msg;
    +        }
    +    }
    +
    +    return;
    +}
    +
     sub check_pgbouncer_checksum {
     
         ## Verify the checksum of all pgbouncer settings
    @@ -8910,6 +8981,31 @@ =head2 B
     checksum must be provided as the C<--mrtg> argument. The fourth line always gives the 
     current checksum.
     
    +=head2 B
    +
    +(C) Checks that all the pgAgent jobs
    +that have executed in the preceding interval of time have succeeded. This is
    +done by checking for any steps that have a non-zero result.
    +
    +Either C<--warning> or C<--critical>, or both, may be specified as times, and
    +jobs will be checked for failures withing the specified periods of time before
    +the current time. Valid units are seconds, minutes, hours, and days; all can
    +be abbreviated to the first letter. If no units are given, 'seconds' are
    +assumed.
    +
    +Example 1: Give a critical when any jobs executed in the last day have failed.
    +
    +  check_postgres_pgagent_jobs --critical=1d
    +
    +Example 2: Give a warning when any jobs executed in the last week have failed.
    +
    +  check_postgres_pgagent_jobs --warning=7d
    +
    +Example 3: Give a critical for jobs that have failed in the last 2 hours and a
    +warning for jobs that have failed in the last 4 hours:
    +
    +  check_postgres_pgagent_jobs --critical=2h --warning=4h
    +
     =head2 B
     
     (C) Check on the age of any existing prepared transactions. 
    diff --git a/check_postgres.pl.html b/check_postgres.pl.html
    index 3ffef636..ea19b1ff 100644
    --- a/check_postgres.pl.html
    +++ b/check_postgres.pl.html
    @@ -79,6 +79,7 @@
     		
  • pgb_pool_maxwait
  • pgbouncer_backends
  • pgbouncer_checksum
  • +
  • pgagent_jobs
  • prepared_txns
  • query_runtime
  • query_time
  • @@ -1234,6 +1235,27 @@

    pgbouncer_checksum

    current checksum.

    +

    pgagent_jobs

    +

    (symlink: check_postgres_pgagent_jobs) Checks that all the pgAgent jobs +that have executed in the preceding interval of time have succeeded. This is +done by checking for any steps that have a non-zero result.

    +

    Either --warning or --critical, or both, may be specified as times, and +jobs will be checked for failures withing the specified periods of time before +the current time. Valid units are seconds, minutes, hours, and days; all can +be abbreviated to the first letter. If no units are given, 'seconds' are +assumed.

    +

    Example 1: Give a critical when any jobs executed in the last day have failed.

    +
    +  check_postgres_pgagent_jobs --critical=1d
    +

    Example 2: Give a warning when any jobs executed in the last week have failed.

    +
    +  check_postgres_pgagent_jobs --warning=7d
    +

    Example 3: Give a critical for jobs that have failed in the last 2 hours and a +warning for jobs that have failed in the last 4 hours:

    +
    +  check_postgres_pgagent_jobs --critical=2h --warning=4h
    +

    +

    prepared_txns

    (symlink: check_postgres_prepared_txns) Check on the age of any existing prepared transactions. Note that most people will NOT use prepared transactions, as they are part of two-part commit diff --git a/t/02_pgagent_jobs.t b/t/02_pgagent_jobs.t new file mode 100644 index 00000000..470be2dc --- /dev/null +++ b/t/02_pgagent_jobs.t @@ -0,0 +1,242 @@ +#!/usr/bin/perl -w + +## Test the "pgagent_jobs" action + +use 5.006; +use strict; +use warnings; +use Test::More tests => 48; +#use Test::More 'no_plan'; +use lib 't','.'; +use CP_Testing; + +my $cp = CP_Testing->new({ default_action => 'pgagent_jobs' }); +my $dbh = $cp->test_database_handle; +my $S = q{Action 'pgagent_jobs'}; +my $label = 'POSTGRES_PGAGENT_JOBS'; +my $tname = 'cp_pgagent_jobs_test'; + +# Mock NOW(). +like $cp->run('foobar=12'), qr{Usage:}, "$S fails when called with an invalid option"; + +like $cp->run('-w=abc'), qr{must be a valid time}, "$S fails with invalid -w"; +like $cp->run('-c=abc'), qr{must be a valid time}, "$S fails with invalid -c"; + +# Set up a dummy pgagent schema. +$dbh->{AutoCommit} = 1; +$dbh->do(q{ + SET client_min_messages TO warning; + CREATE SCHEMA pgagent; + + CREATE TABLE pgagent.pga_job ( + jobid serial NOT NULL PRIMARY KEY, + jobname text NOT NULL + ); + + CREATE TABLE pgagent.pga_jobstep ( + jstid serial NOT NULL PRIMARY KEY, + jstjobid int4 NOT NULL REFERENCES pgagent.pga_job(jobid), + jstname text NOT NULL + ); + + CREATE TABLE pgagent.pga_joblog ( + jlgid serial NOT NULL PRIMARY KEY, + jlgjobid int4 NOT NULL REFERENCES pgagent.pga_job(jobid), + jlgstart timestamptz NOT NULL DEFAULT current_timestamp, + jlgduration interval NULL + ); + + CREATE TABLE pgagent.pga_jobsteplog ( + jsljlgid int4 NOT NULL REFERENCES pgagent.pga_joblog(jlgid), + jsljstid int4 NOT NULL REFERENCES pgagent.pga_jobstep(jstid), + jslresult int4 NULL, + jsloutput text + ); + RESET client_min_messages; +}); +END { $dbh->do(q{ + SET client_min_messages TO warning; + DROP SCHEMA pgagent CASCADE; + RESET client_min_messages; +}) if $dbh; } + +like $cp->run('-c=1d'), qr{^$label OK: DB "postgres"}, "$S returns ok for no jobs"; + +for my $time (qw/seconds minutes hours days/) { + like $cp->run("-w=1000000$time"), qr{^$label OK: DB "postgres"}, + qq{$S returns ok for no pgagent_jobs with a unit of $time}; + (my $singular = $time) =~ s/s$//; + like $cp->run("-w=1000000$singular"), qr{^$label OK: DB "postgres"}, + qq{$S returns ok for no pgagent_jobs with a unit of $singular}; + my $short = substr $time, 0, 1; + like $cp->run("-w=1000000$short"), qr{^$label OK: DB "postgres"}, + qq{$S returns ok for no pgagent_jobs with a unit of $short}; +} + +my ($now, $back_6_hours, $back_30_hours) = $dbh->selectrow_array(q{ + SELECT NOW(), NOW() - '6 hours'::interval, NOW() - '30 hours'::interval +}); + +# Let's add some jobs +$dbh->do(qq{ + -- Two jobs. + INSERT INTO pgagent.pga_job (jobid, jobname) + VALUES (1, 'Backup'), (2, 'Restore'); + + -- Each job has two steps. + INSERT INTO pgagent.pga_jobstep (jstid, jstjobid, jstname) + VALUES (11, 1, 'pd_dump'), (21, 1, 'vacuum'), + (12, 2, 'pd_restore'), (22, 2, 'analyze'); + + -- Execute each job twice. + INSERT INTO pgagent.pga_joblog (jlgid, jlgjobid, jlgstart, jlgduration) + VALUES (31, 1, '$back_6_hours', '1 hour'), + (41, 1, '$back_30_hours', '5m'), + (32, 2, '$back_6_hours', '01:02:00'), + (42, 2, '$back_30_hours', '7m'); + + -- Execute each step twice. + INSERT INTO pgagent.pga_jobsteplog (jsljlgid, jsljstid, jslresult, jsloutput) + VALUES (31, 11, 0, ''), + (31, 21, 0, ''), + (41, 11, 0, ''), + (41, 21, 0, ''), + (32, 12, 0, ''), + (32, 22, 0, ''), + (42, 12, 0, ''), + (42, 22, 0, ''); +}); + +# There should be no failures. +like $cp->run('-c=1d'), qr{^$label OK: DB "postgres"}, + "$S returns ok with only successful jobs"; + +# Make one job fail from before our time. +ok $dbh->do(q{ + UPDATE pgagent.pga_jobsteplog + SET jslresult = 255 + , jsloutput = 'WTF!' + WHERE jsljlgid = 32 + AND jsljstid = 22 +}), 'Make a job fail around 5 hours ago'; + +like $cp->run('-c=2h'), qr{^$label OK: DB "postgres"}, + "$S -c=2h returns ok with failed job before our time"; + +like $cp->run('-c=6h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -c=6h returns critical with failed job within our time"; + +like $cp->run('-w=2h'), qr{^$label OK: DB "postgres"}, + "$S -w=2h returns ok with failed job before our time"; + +like $cp->run('-w=6h'), + qr{^$label WARNING: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -w=6h returns warninf with failed job within our time"; + +like $cp->run('-w=2h'), qr{^$label OK: DB "postgres"}, + "$S -w=2h returns ok with failed job before our time"; + +like $cp->run('-w=4h -c=2h'), qr{^$label OK: DB "postgres"}, + "$S -w=4h =c=2h returns ok with failed job before our time"; + +like $cp->run('-w=5h -c=2h'), + qr{^$label WARNING: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -w=5h =c=2h returns warning with failed job within our time"; + +like $cp->run('-w=2h -c=5h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -w=2h =c=5h returns critical with failed job within our time"; + +like $cp->run('-w=5h -c=5h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -w=5h =c=5h returns critical with failed job within our time"; + +# Make a second job fail, back 30 hours. +ok $dbh->do(q{ + UPDATE pgagent.pga_jobsteplog + SET jslresult = 64 + , jsloutput = 'OMGWTFLOL!' + WHERE jsljlgid = 42 + AND jsljstid = 22 +}), 'Make a job fail around 29 hours ago'; + +like $cp->run('-c=2h'), qr{^$label OK: DB "postgres"}, + "$S -c=2h returns ok with failed job before our time"; + +like $cp->run('-c=6h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -c=6h returns critical with failed job within our time"; + +like $cp->run('-w=2h'), qr{^$label OK: DB "postgres"}, + "$S -w=2h returns ok with failed job before our time"; + +like $cp->run('-w=6h'), + qr{^$label WARNING: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -w=6h returns warninf with failed job within our time"; + +like $cp->run('-w=2h'), qr{^$label OK: DB "postgres"}, + "$S -w=2h returns ok with failed job before our time"; + +like $cp->run('-w=4h -c=2h'), qr{^$label OK: DB "postgres"}, + "$S -w=4h =c=2h returns ok with failed job before our time"; + +like $cp->run('-w=5h -c=2h'), + qr{^$label WARNING: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -w=5h =c=2h returns warning with failed job within our time"; + +like $cp->run('-w=2h -c=5h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -w=2h =c=5h returns critical with failed job within our time"; + +like $cp->run('-w=5h -c=5h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -w=5h -c=5h returns critical with failed job within our time"; + +# Go back futher in time! +like $cp->run('-w=30h -c=2h'), + qr{^$label WARNING: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!}, + "$S -w=30h -c=5h returns warning for older failed job"; + +like $cp->run('-w=30h -c=6h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!; 64 Restore/analyze: OMGWTFLOL!}, + "$S -w=30h -c=6h returns critical with both jobs, more recent critical"; + +like $cp->run('-c=30h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!; 64 Restore/analyze: OMGWTFLOL!}, + "$S -c=30h returns critical with both failed jobs"; + +like $cp->run('-w=30h'), + qr{^$label WARNING: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!; 64 Restore/analyze: OMGWTFLOL!}, + "$S -w=30h returns critical with both failed jobs"; + +# Try with critical recent and warning longer ago. +like $cp->run('-w=30h -c=6h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!; 64 Restore/analyze: OMGWTFLOL!}, + "$S -w=30h -c=6h returns critical with both failed jobs"; + +# Try with warning recent and critical longer ago. +like $cp->run('-c=30h -w=6h'), + qr{^$label CRITICAL: DB "postgres" [()][^)]+[)] 255 Restore/analyze: WTF!; 64 Restore/analyze: OMGWTFLOL!}, + "$S -c=30h -w=6h returns critical with both failed jobs"; + +# Undo the more recent failure. +ok $dbh->do(q{ + UPDATE pgagent.pga_jobsteplog + SET jslresult = 0 + , jsloutput = '' + WHERE jsljlgid = 32 + AND jsljstid = 22 +}), 'Unfail the more recent failed job'; + +like $cp->run('-c=6h'), qr{^$label OK: DB "postgres"}, + "$S -c=6h should now return ok"; + +like $cp->run('-c=30h'), qr{^$label CRITICAL: DB "postgres"}, + "$S -c=30h should return critical"; + +like $cp->run('-w=6h'), qr{^$label OK: DB "postgres"}, + "$S -w=6h should now return ok"; + +like $cp->run('-w=30h'), qr{^$label WARNING: DB "postgres"}, + "$S -w=30h should return warning"; From b91c22dbb84e52c0dc88ae5479b34733f375b027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Sun, 22 Jan 2012 20:54:34 +0800 Subject: [PATCH 38/42] Minor change in bloat test The test was loading Data::Dumepr but not using it. --- t/02_bloat.t | 1 - 1 file changed, 1 deletion(-) diff --git a/t/02_bloat.t b/t/02_bloat.t index cbb9c010..5614b88a 100644 --- a/t/02_bloat.t +++ b/t/02_bloat.t @@ -5,7 +5,6 @@ use 5.006; use strict; use warnings; -use Data::Dumper; use Test::More tests => 30; use lib 't','.'; use CP_Testing; From 0df76f3ac49f8b31337b3ce124e09fa885450d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Sun, 22 Jan 2012 21:11:30 +0800 Subject: [PATCH 39/42] Update History for 2.20.0 Add check for pgagent jobs (David E. Wheeler) --- check_postgres.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/check_postgres.pl b/check_postgres.pl index 93a7751f..d7c559e7 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -9615,6 +9615,10 @@ =head1 HISTORY =over 4 +=item B + + Add check for pgagent jobs (David E. Wheeler) + =item B January 17, 2012 Add the --assume-prod option (Cédric Villemain) From 3f7e6d707f40e898014278e38464c3c2980b1bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Sun, 22 Jan 2012 22:38:00 +0800 Subject: [PATCH 40/42] Revert "Minor change in bloat test" This reverts commit 7788d081ab5ed74d53f699bc7333e00f2bb59d9a. GSM: Data::Dumper is handy for when you do want to Dump something. --- t/02_bloat.t | 1 + 1 file changed, 1 insertion(+) diff --git a/t/02_bloat.t b/t/02_bloat.t index 5614b88a..cbb9c010 100644 --- a/t/02_bloat.t +++ b/t/02_bloat.t @@ -5,6 +5,7 @@ use 5.006; use strict; use warnings; +use Data::Dumper; use Test::More tests => 30; use lib 't','.'; use CP_Testing; From 39843ef3aac4611760b4044b5929d6f36a097853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Mon, 23 Jan 2012 06:51:12 +0800 Subject: [PATCH 41/42] Fix the createlang during init There was a copy-n-paste error, only affecting < 8.1 . --- t/CP_Testing.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/CP_Testing.pm b/t/CP_Testing.pm index 6279322f..f7d58d18 100644 --- a/t/CP_Testing.pm +++ b/t/CP_Testing.pm @@ -249,7 +249,7 @@ sub test_database_handle { $SQL = qq{SELECT * FROM pg_language WHERE lanname = '$lang'}; $res = qx{psql -Ax -qt -d postgres -q -h "$host" -c "$SQL"}; if ($res !~ /$lang/) { - my $createlang = $ENV{PGBINDIR} ? "$ENV{PGBINDIR}/createlang" : 'pg_ctl'; + my $createlang = $ENV{PGBINDIR} ? "$ENV{PGBINDIR}/createlang" : 'createlang'; $COM = qq{$createlang -d postgres -h "$host" $lang}; system $COM; } From b243ff106e2ae1efd1aa7bb97fb814f4788bad48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Mon, 23 Jan 2012 06:44:11 +0800 Subject: [PATCH 42/42] Allows PGBINDIR in check_postgresrc This is the same approach as it is with PSQL variable (the $NO_PSQL_OPTION variable har-coded *MUST* be set to 0 to use them). PGBINDIR can be set in ENV, hard-coded in check_postgres.pl or set via command-line argument. PGCONTROLDATA and PSQL can still be used but should be deprecated. the logic is if NO_PSQL_OPTION=1 : * that PGBINDIR can be set via environment variable, but not via config file or command-line argument. * that PSQL can not be set explicitly, but derived from PGBINDIR --- check_postgres.pl | 92 +++++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 31 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index d7c559e7..514d634d 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -32,7 +32,7 @@ package check_postgres; our $VERSION = '2.19.0'; -use vars qw/ %opt $PSQL $res $COM $SQL $db /; +use vars qw/ %opt $PGBINDIR $PSQL $res $COM $SQL $db /; ## Which user to connect as if --dbuser is not given $opt{defaultuser} = 'postgres'; @@ -43,11 +43,11 @@ package check_postgres; ## What type of output to use by default our $DEFAULT_OUTPUT = 'nagios'; -## If psql is not in your path, it is recommended to hardcode it here, -## as an alternative to the --PSQL option -$PSQL = ''; +## If psql binaries are not in your path, it is recommended to hardcode it here, +## as an alternative to the --PGBINDIR option +$PGBINDIR = ''; -## If this is true, $opt{PSQL} is disabled for security reasons +## If this is true, $opt{PSQL} and $opt{PGBINDIR} are disabled for security reasons our $NO_PSQL_OPTION = 1; ## If true, we show how long each query took by default. Requires Time::HiRes to be installed. @@ -125,6 +125,7 @@ package check_postgres; 'custom-nostring' => q{Must provide a query string}, 'database' => q{database}, 'dbsize-version' => q{Target database must be version 8.1 or higher to run the database_size action}, + 'depr-pgcontroldata' => q{PGCONTROLDATA is deprecated, use PGBINDIR instead.}, 'die-action-version' => q{Cannot run "$1": server version must be >= $2, but is $3}, 'die-badtime' => q{Value for '$1' must be a valid time. Examples: -$2 1s -$2 "10 minutes"}, 'die-badversion' => q{Invalid version string: $1}, @@ -188,7 +189,7 @@ package check_postgres; 'opt-psql-noexist' => q{Cannot find given psql executable: $1}, 'opt-psql-nofind' => q{Could not find a suitable psql executable}, 'opt-psql-nover' => q{Could not determine psql version}, - 'opt-psql-restrict' => q{Cannot use the --PSQL option when NO_PSQL_OPTION is on}, + 'opt-psql-restrict' => q{Cannot use the --PGBINDIR or --PSQL option when NO_PSQL_OPTION is on}, 'pgagent-jobs-ok' => q{No failed jobs}, 'pgbouncer-pool' => q{Pool=$1 $2=$3}, 'pgb-backends-mrtg' => q{DB=$1 Max connections=$2}, @@ -439,7 +440,7 @@ package check_postgres; 'opt-psql-noexist' => q{Ne peut pas trouver l'exécutable psql indiqué : $1}, 'opt-psql-nofind' => q{N'a pas pu trouver un psql exécutable}, 'opt-psql-nover' => q{N'a pas pu déterminer la version de psql}, - 'opt-psql-restrict' => q{Ne peut pas utiliser l'option --PSQL si NO_PSQL_OPTION est activé}, + 'opt-psql-restrict' => q{Ne peut pas utiliser l'option --PGBINDIR ou --PSQL si NO_PSQL_OPTION est activé}, 'pgbouncer-pool' => q{Pool=$1 $2=$3}, 'pgb-backends-mrtg' => q{base=$1 connexions max=$2}, 'pgb-backends-msg' => q{$1 connexions sur $2 ($3%)}, @@ -959,6 +960,7 @@ package check_postgres; 'dbpass|dbpass1=s@', 'dbservice|dbservice1=s@', + 'PGBINDIR=s', 'PSQL=s', 'tempdir=s', @@ -1217,7 +1219,8 @@ package check_postgres; Other options: --assume-standby-mode assume that server in continious WAL recovery mode --assume-prod assume that server in production mode - --PSQL=FILE location of the psql executable; avoid using if possible + --PGBINDIR=PATH path of the postgresql binaries; avoid using if possible + --PSQL=FILE (deprecated) location of the psql executable; avoid using if possible -v, --verbose verbosity level; can be used more than once to increase the level -h, --help display this help information --man display the full manual @@ -1261,12 +1264,6 @@ package check_postgres; } } -## Check the current database mode -our $STANDBY = 0; -our $MASTER = 0; -make_sure_standby_mode() if $opt{'assume-standby-mode'}; -make_sure_prod() if $opt{'assume-prod'}; - ## We don't (usually) want to die, but want a graceful Nagios-like exit instead sub ndie { eval { File::Temp::cleanup(); }; @@ -1321,21 +1318,29 @@ sub msg_en { ## Everything from here on out needs psql, so find and verify a working version: if ($NO_PSQL_OPTION) { - delete $opt{PSQL} and ndie msg('opt-psql-restrict'); + (delete $opt{PGBINDIR} or delete $opt{PSQL}) and ndie msg('opt-psql-restrict'); } - -if (! defined $PSQL or ! length $PSQL) { - if (exists $opt{PSQL}) { - $PSQL = $opt{PSQL}; - $PSQL =~ m{^/[\w\d\/]*psql$} or ndie msg('opt-psql-badpath'); - -e $PSQL or ndie msg('opt-psql-noexist', $PSQL); +if (! defined $PGBINDIR or ! length $PGBINDIR) { + if (defined $ENV{PGBINDIR} and length $ENV{PGBINDIR}){ + $PGBINDIR = $ENV{PGBINDIR}; + } + elsif (defined $opt{PGBINDIR} and length $opt{PGBINDIR}){ + $PGBINDIR = $opt{PGBINDIR}; } else { - my $psql = $ENV{PGBINDIR} ? "$ENV{PGBINDIR}/psql" : 'psql'; - chomp($PSQL = qx{which $psql}); - $PSQL or ndie msg('opt-psql-nofind'); + undef $PGBINDIR; } } +if (exists $opt{PSQL}) { + $PSQL = $opt{PSQL}; + $PSQL =~ m{^/[\w\d\/]*psql$} or ndie msg('opt-psql-badpath'); + -e $PSQL or ndie msg('opt-psql-noexist', $PSQL); +} +else { + my $psql = (defined $PGBINDIR) ? "$PGBINDIR/psql" : "psql"; + chomp($PSQL = qx{which "$psql"}); + $PSQL or ndie msg('opt-psql-nofind'); +} -x $PSQL or ndie msg('opt-psql-noexec', $PSQL); $res = qx{$PSQL --version}; $res =~ /psql\D+(\d+\.\d+)/ or ndie msg('opt-psql-nover'); @@ -1346,6 +1351,12 @@ sub msg_en { $opt{defaultdb} = $psql_version >= 8.0 ? 'postgres' : 'template1'; $opt{defaultdb} = 'pgbouncer' if $action =~ /^pgb/; +## Check the current database mode +our $STANDBY = 0; +our $MASTER = 0; +make_sure_standby_mode() if $opt{'assume-standby-mode'}; +make_sure_prod() if $opt{'assume-prod'}; + ## Create the list of databases we are going to connect to my @targetdb = setup_target_databases(); @@ -3162,10 +3173,18 @@ sub open_controldata { } ## Run pg_controldata - my $pgc - = $ENV{PGCONTROLDATA} ? $ENV{PGCONTROLDATA} - : $ENV{PGBINDIR} ? "$ENV{PGBINDIR}/pg_controldata" - : 'pg_controldata'; + ## We still catch deprecated option + my $pgc; + if (defined $ENV{PGCONTROLDATA} and length $ENV{PGCONTROLDATA}) { + # ndie msg('depr-pgcontroldata'); + $pgc = "$ENV{PGCONTROLDATA}"; + } + else { + $pgc = (defined $PGBINDIR) ? "$PGBINDIR/pg_controldata" : "pg_controldata"; + chomp($pgc = qx{which "$pgc"}); + } + -x $pgc or ndie msg('opt-psql-noexec', $pgc); + $COM = qq{$pgc "$dir"}; eval { $res = qx{$COM 2>&1}; @@ -8058,8 +8077,19 @@ =head1 OTHER OPTIONS Enables test mode. See the L section below. +=item B<--PGBINDIR=PATH> + +Tells the script where to find the psql binaries. Useful if you have more than +one version of the PostgreSQL executables on your system, or if there are not +in your path. Note that this option is in all uppercase. By default, this option +is I. To enable it, you must change the C<$NO_PSQL_OPTION> near the +top of the script to 0. Avoid using this option if you can, and instead use +environement variable c or hard-coded C<$PGBINDIR> variable, also near +the top of the script, to set the path to the PostgreSQL to use. + =item B<--PSQL=PATH> +I<(deprecated, this option may be removed in a future release!)> Tells the script where to find the psql program. Useful if you have more than one version of the psql executable on your system, or if there is no psql program in your path. Note that this option is in all uppercase. By default, this option @@ -8282,9 +8312,8 @@ =head2 B The data directory must be set, either by the environment variable C, or passing the C<--datadir> argument. It returns the number of seconds since the last checkpoint was run, as determined by parsing the call to C. Because of this, the -pg_controldata executable must be available in the current path. Alternatively, you can -set the environment variable C to the exact location of the pg_controldata -executable, or you can specify C as the directory that it lives in. +pg_controldata executable must be available in the current path. Alternatively, +you can specify C as the directory that it lives in. It is also possible to use the special options I<--assume-prod> or I<--assume-standby-mode>, if the mode found is not the one expected, a CRITICAL is emitted. @@ -9550,6 +9579,7 @@ =head1 FILES =head1 ENVIRONMENT VARIABLES The environment variable I<$ENV{HOME}> is used to look for a F<.check_postgresrc> file. +The environment variable I<$ENV{PGBINDIR}> is used to look for PostgreSQL binaries. =head1 TIPS AND TRICKS pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy