$Data::Dumper::Indent = 2;
$Data::Dumper::Useqq = 1;
-our $VERSION = '2.0.1';
+our $VERSION = '2.1.0';
use vars qw/ %opt $PSQL $res $COM $SQL $db /;
## Quick hash to put normal action information in one place:
our $action_info = {
# Name # clusterwide? # helpstring
+ autovac_freeze => [1, 'Checks how close databases are to autovacuum_freeze_max_age.'],
backends => [1, 'Number of connections, compared to max_connections.'],
bloat => [0, 'Check for table and index bloat.'],
connection => [0, 'Simple connection check.'],
## If in test mode, verify that we can run each requested action
our %testaction = (
+ autovac_freeze => 'VERSION: 8.2',
last_vacuum => 'ON: stats_row_level(<8.3) VERSION: 8.2',
last_analyze => 'ON: stats_row_level(<8.3) VERSION: 8.2',
last_autovacuum => 'ON: stats_row_level(<8.3) VERSION: 8.2',
## Test of replication
check_replicate_row() if $action eq 'replicate_row';
+## See how close we are to autovacuum_freeze_max_age
+check_autovac_freeze() if $action eq 'autovac_freeze';
+
finishup();
exit 0;
my $regex = ($string =~ s/^~//) ? '~' : '=';
$string =~ /^\w+$/ or die qq{Invalid option\n};
}
+ elsif ('percent' eq $type) {
+ if (length $critical) {
+ if ($critical !~ /^\d+\%$/) {
+ ndie qq{Invalid 'critical' option: must be percentage\n};
+ }
+ }
+ if (length $warning) {
+ if ($warning !~ /^\d+\%$/) {
+ ndie qq{Invalid 'warning' option: must be percentage\n};
+ }
+ }
+ }
elsif ('size or percent' eq $type) {
if (length $critical) {
if ($critical =~ $sizere) {
} ## end of validate_range
+sub check_autovac_freeze {
+
+ ## Check how close all databases are to autovacuum_freeze_max_age
+ ## Supports: Nagios, MRTG
+ ## It makes no sense to run this more than once on the same cluster
+ ## Warning and criticals are percentages
+ ## Can also ignore databases with exclude, and limit with include
+
+ my ($warning, $critical) = validate_range
+ ({
+ type => 'percent',
+ default_warning => '90%',
+ default_critical => '95%',
+ forcemrtg => 1,
+ });
+
+ (my $w = $warning) =~ s/\D//;
+ (my $c = $critical) =~ s/\D//;
+ my $SQL = q{SELECT freez, txns, ROUND(100*(txns/freez::float)) AS perc, datname}.
+ q{ FROM (SELECT foo.freez::int, age(datfrozenxid) AS txns, datname}.
+ q{ FROM pg_database d JOIN (SELECT setting AS freez FROM pg_settings WHERE name = 'autovacuum_freeze_max_age') AS foo}.
+ q{ ON (true)) AS foo2 ORDER BY 3 DESC, 4 ASC};
+ my $info = run_command($SQL, {regex => qr[\w+] } );
+
+ for $db (@{$info->{db}}) {
+ my (@crit,@warn,@ok);
+ my ($maxp,$maxt,$maxdb) = (0,0,''); ## used by MRTG only
+ SLURP: while ($db->{slurp} =~ /\s*(\d+) \|\s+(\d+) \|\s+(\d+) \| (.+?)$/gsm) {
+ my ($freeze,$age,$percent,$dbname) = ($1,$2,$3,$4);
+ next SLURP if skip_item($dbname);
+
+ if ($MRTG) {
+ if ($percent > $maxp) {
+ $maxdb = $dbname;
+ }
+ elsif ($percent == $maxp) {
+ $maxdb .= sprintf "%s$dbname", length $maxdb ? ' | ' : '';
+ }
+ $maxt = $age if $age > $maxt;
+ next;
+ }
+
+ my $msg = "$dbname=$percent\% ($age)";
+ $db->{perf} .= " $msg";
+ if (length $critical and $percent >= $c) {
+ push @crit => $msg;
+ }
+ elsif (length $warning and $percent >= $w) {
+ push @warn => $msg;
+ }
+ else {
+ push @ok => $msg;
+ }
+ }
+ if ($MRTG) {
+ do_mrtg({one => $maxp, two => $maxt, msg => $maxdb});
+ }
+ if (@crit) {
+ add_critical join ' ' => @crit;
+ }
+ elsif (@warn) {
+ add_warning join ' ' => @warn;
+ }
+ else {
+ add_ok join ' ' => @ok;
+ }
+ }
+
+ return;
+
+} ## end of check_autovac_freeze
+
+
sub check_backends {
## Check the number of connections
## critical = 12 -- complain if there are 12 or more connections
## critical = 95% -- complain if >= 95% of available connections are used
## critical = -5 -- complain if there are only 5 or fewer connection slots left
- ## Can also ignore databases with exclude, and limit with include
## The former two options only work with simple numbers - no percentage or negative
+ ## Can also ignore databases with exclude, and limit with include
my $warning = $opt{warning} || '90%';
my $critical = $opt{critical} || '95%';
} ## end of check_backends
-
sub check_bloat {
## Check how bloated the tables and indexes are
=head1 VERSION
-This documents describes B<check_postgres.pl> version 2.0.1
+This documents describes B<check_postgres.pl> version 2.1.0
=head1 SYNOPSIS
=over 4
+=item B<autovac_freeze> (symlink: C<check_postgres_autovac_freeze>)
+
+Checks how close each database is to the Postgres B<autovacuum_freeze_max_age> setting. This
+action will only work for databases version 8.2 or higher. The I<--warning> and
+I<--critical> options should be expressed as percentages. The 'age' of the transactions
+in each database is compared to the autovacuum_freeze_max_age setting (200 million by default)
+to generate a rounded percentage. The default values are B<90%> for the warning and B<95%> for
+the critical. Databases can be filtered by use of the I<--include> and I<--exclude> options. See
+the L</"BASIC FILTERING"> section for more details.
+
+Example 1: Give a warning when any databases on port 5432 are above 80%
+
+ check_postgres_autovac_freeze --port=5432 --warning="80%"
+
+For MRTG output, the highest overall percentage is reported on the first line, and the highest age is
+reported on the second line. All databases which have the percentage from the first line are reported
+on the fourth line, separated by a pipe symbol.
+
=item B<backends> (symlink: C<check_postgres_backends>)
Checks the current number of connections for one or more databases, and optionally
=over 4
+=item B<Version 2.1.0> (July 18, 2008)
+
+Add the "autovac_freeze" action, thanks to Robert Treat for the idea and design.
+
=item B<Version 2.0.1> (July 16, 2008)
Optimizations to speed up the "bloat" action quite a bit.
</p>
<hr />
<h1><a name="version">VERSION</a></h1>
-<p>This documents describes <strong>check_postgres.pl</strong> version 2.0.1</p>
+<p>This documents describes <strong>check_postgres.pl</strong> version 2.1.0</p>
<p>
</p>
<hr />
critical is an effective way to turn warnings off and always give a critical.</p>
<p>The current supported actions are:</p>
<dl>
+<dt><strong><a name="autovac_freeze" class="item"><strong>autovac_freeze</strong> (symlink: <code>check_postgres_autovac_freeze</code>)</a></strong>
+
+<dd>
+<p>Checks how close each database is to the Postgres <strong>autovacuum_freeze_max_age</strong> setting. This
+action will only work for databases version 8.2 or higher. The <em>--warning</em> and
+<em>--critical</em> options should be expressed as percentages. The 'age' of the transactions
+in each database is compared to the autovacuum_freeze_max_age setting (200 million by default)
+to generate a rounded percentage. The default values are <strong>90%</strong> for the warning and <strong>95%</strong> for
+the critical. Databases can be filtered by use of the <em>--include</em> and <em>--exclude</em> options. See
+the <a href="#basic_filtering">BASIC FILTERING</a> section for more details.</p>
+</dd>
+<dd>
+<p>Example 1: Give a warning when any databases on port 5432 are above 80%</p>
+</dd>
+<dd>
+<pre>
+ check_postgres_autovac_freeze --port=5432 --warning="80%"</pre>
+</dd>
+<dd>
+<p>For MRTG output, the highest overall percentage is reported on the first line, and the highest age is
+reported on the second line. All databases which have the percentage from the first line are reported
+on the fourth line, separated by a pipe symbol.</p>
+</dd>
+</li>
<dt><strong><a name="backends" class="item"><strong>backends</strong> (symlink: <code>check_postgres_backends</code>)</a></strong>
<dd>
<h1><a name="history">HISTORY</a></h1>
<p>Items not specifically attributed are by Greg Sabino Mullane.</p>
<dl>
+<dt><strong><a name="0" class="item"><strong>Version 2.1.0</strong> (July 18, 2008)</a></strong>
+
+<dd>
+<p>Add the "autovac_freeze" action, thanks to Robert Treat for the idea and design.</p>
+</dd>
+</li>
<dt><strong><a name="1" class="item"><strong>Version 2.0.1</strong> (July 16, 2008)</a></strong>
<dd>
-<p>Optimizations to speed up the "bloat" action quite a bit.</p>
+<p>Optimizations to speed up the "bloat" action quite a bit.
+Fix "version" action to not always output in mrtg mode.</p>
</dd>
</li>
-<dt><strong><a name="0" class="item"><strong>Version 2.0.0</strong> (July 15, 2008)</a></strong>
+<dt><strong><strong>Version 2.0.0</strong> (July 15, 2008)</strong>
<dd>
<p>Add support for MRTG and "simple" output options.