diff --git a/README b/README index e6bfc1b..af57119 100644 --- a/README +++ b/README @@ -772,6 +772,12 @@ COMPATIBILITY You can use multiple "--exclude REGEX" parameters. + This service supports a "--analyze-table-min-size" parameter to + exclude small relations. We use the `pg_relation_size()` function + to filter out those relations that are smaller than this value, + because the tables and their associated toast tables are processed + separately by autovacuum, and by this probe. This defaults to 1MB. + Required privileges: unprivileged role able to log in all databases. last_vacuum (8.2+) @@ -810,6 +816,12 @@ COMPATIBILITY You can use multiple "--exclude REGEX" parameters. + This service supports a "--vacuum-table-min-size" parameter to + exclude small relations. We use the `pg_relation_size()` function + to filter out those relations that are smaller than this value, + because the tables and their associated toast tables are processed + separately by autovacuum, and by this probe. This defaults to 2MB. + Required privileges: unprivileged role able to log in all databases. locks (all) diff --git a/check_pgactivity b/check_pgactivity index 7fb928f..f5972e6 100755 --- a/check_pgactivity +++ b/check_pgactivity @@ -503,6 +503,8 @@ my %args = ( 'wal_buffers' => undef, 'checkpoint_segments' => undef, 'effective_cache_size' => undef, + 'vacuum-table-min-size' => '2mb', + 'analyze-table-min-size'=> '1mb', 'no_check_autovacuum' => 0, 'no_check_fsync' => 0, 'no_check_enable' => 0, @@ -5270,6 +5272,7 @@ sub check_last_maintenance { my @rs; my $c_limit; my $w_limit; + my $table_min_size; my @perfdata; my @msg_crit; my @msg_warn; @@ -5285,6 +5288,8 @@ sub check_last_maintenance { my @dbexclude = @{ $args{'dbexclude'} }; my $me = 'POSTGRES_LAST_' . uc($type); + $table_min_size = get_size($args{$type . "-table-min-size"}); + # warning and critical are mandatory. pod2usage( -message => "FATAL: you must specify critical and warning thresholds.", @@ -5334,6 +5339,7 @@ sub check_last_maintenance { ||'$c_limit $w_limit')) FROM pg_stat_all_tables a WHERE schemaname NOT LIKE 'pg_temp_%' + AND pg_relation_size(relid) >= $table_min_size AND schemaname NOT LIKE 'information_schema' AND (('${type}' = 'analyze' AND schemaname NOT LIKE 'pg_toast') -- TOAST tables aren't ANALYZEd OR ('${type}' = 'vacuum')) @@ -5364,6 +5370,7 @@ sub check_last_maintenance { FROM pg_stat_all_tables a WHERE schemaname NOT LIKE 'pg_temp_%' AND schemaname NOT LIKE 'pg_toast_temp_%' + AND pg_relation_size(relid) >= $table_min_size AND schemaname NOT LIKE 'information_schema' AND (('${type}' = 'analyze' AND schemaname NOT LIKE 'pg_toast') -- TOAST tables aren't ANALYZEd OR ('${type}' = 'vacuum')) @@ -5396,6 +5403,7 @@ sub check_last_maintenance { FROM pg_stat_all_tables a WHERE schemaname NOT LIKE 'pg_temp_%' AND schemaname NOT LIKE 'pg_toast_temp_%' + AND pg_relation_size(relid) >= $table_min_size AND schemaname NOT LIKE 'information_schema' AND (('${type}' = 'analyze' AND schemaname NOT LIKE 'pg_toast') -- TOAST tables aren't ANALYZEd OR ('${type}' = 'vacuum')) @@ -5438,6 +5446,7 @@ sub check_last_maintenance { JOIN pg_class b on a.relid = b.oid WHERE schemaname NOT LIKE 'pg_temp_%' AND schemaname NOT LIKE 'pg_toast_temp_%' + AND pg_relation_size(relid) >= $table_min_size AND schemaname NOT LIKE 'information_schema' AND (('${type}' = 'analyze' AND schemaname NOT LIKE 'pg_toast') -- TOAST tables aren't ANALYZEd OR ('${type}' = 'vacuum')) @@ -10035,6 +10044,8 @@ GetOptions( 'dump-status-file!', 'dump-bin-file:s', 'effective_cache_size=i', + 'vacuum-table-min-size=s', + 'analyze-table-min-size=s', 'exclude=s', 'format|F=s', 'global-pattern=s', diff --git a/t/01-last_analyze.t b/t/01-last_analyze.t index c2dea02..c785e9c 100644 --- a/t/01-last_analyze.t +++ b/t/01-last_analyze.t @@ -50,6 +50,7 @@ sleep(1); $node->command_checks_all( [ './check_pgactivity', '--service' => 'last_analyze', + '--analyze-table-min-size' => 0, '--username' => $ENV{'USER'} || 'postgres', '--format' => 'human', '--dbname' => 'testdb', @@ -106,6 +107,7 @@ SKIP: { $node->command_checks_all( [ './check_pgactivity', '--service' => 'last_analyze', + '--analyze-table-min-size' => 0, '--username' => $ENV{'USER'} || 'postgres', '--format' => 'human', '--dbname' => 'testdb', @@ -145,6 +147,7 @@ push @stdout, ( $node->command_checks_all( [ './check_pgactivity', '--service' => 'last_analyze', + '--analyze-table-min-size' => 0, '--username' => $ENV{'USER'} || 'postgres', '--format' => 'human', '--dbname' => 'testdb', @@ -182,6 +185,7 @@ push @stdout, ( $node->command_checks_all( [ './check_pgactivity', '--service' => 'last_analyze', + '--analyze-table-min-size' => 0, '--username' => $ENV{'USER'} || 'postgres', '--format' => 'human', '--dbname' => 'testdb', diff --git a/t/01-last_vacuum.t b/t/01-last_vacuum.t index b7df764..a117af7 100644 --- a/t/01-last_vacuum.t +++ b/t/01-last_vacuum.t @@ -10,7 +10,7 @@ use warnings; use lib 't/lib'; use pgNode; use TestLib (); -use Test::More tests => 33; +use Test::More tests => 39; my $node = pgNode->get_new_node('prod'); my $pga_data = "$TestLib::tmp_check/pga.data"; @@ -50,6 +50,7 @@ sleep(1); $node->command_checks_all( [ './check_pgactivity', '--service' => 'last_vacuum', + '--vacuum-table-min-size' => 0, '--username' => $ENV{'USER'} || 'postgres', '--format' => 'human', '--dbname' => 'template1', @@ -107,6 +108,7 @@ SKIP: { $node->command_checks_all( [ './check_pgactivity', '--service' => 'last_vacuum', + '--vacuum-table-min-size' => 0, '--username' => $ENV{'USER'} || 'postgres', '--format' => 'human', '--dbname' => 'testdb', @@ -146,6 +148,7 @@ push @stdout, ( $node->command_checks_all( [ './check_pgactivity', '--service' => 'last_vacuum', + '--vacuum-table-min-size' => 0, '--username' => $ENV{'USER'} || 'postgres', '--format' => 'human', '--dbname' => 'testdb', @@ -183,6 +186,7 @@ push @stdout, ( $node->command_checks_all( [ './check_pgactivity', '--service' => 'last_vacuum', + '--vacuum-table-min-size' => 0, '--username' => $ENV{'USER'} || 'postgres', '--format' => 'human', '--dbname' => 'testdb', @@ -196,6 +200,50 @@ $node->command_checks_all( [ 'test database with two tables, both vacuumed' ); +# test database with three tables, only one never vacuumed, filtering out small tables + +# we must track the stat activity on pg_class to make sure there was some stat +# activity to avoid the check_pga shortcut when no activity. +($stdout) = $node->psql('testdb', q{ + SELECT n_tup_ins + FROM pg_stat_sys_tables + WHERE relname = 'pg_class' +}); + +$node->psql('testdb', 'CREATE TABLE boo (bar INT)'); + +$node->poll_query_until('testdb', qq{ + SELECT n_tup_ins > $stdout + FROM pg_stat_sys_tables + WHERE relname = 'pg_class' +}); + +@stdout = ( + qr/^Service *: POSTGRES_LAST_VACUUM$/m, + qr/^Returns *: 0 \(OK\)$/m, + qr/^Message *: 1 database\(s\) checked$/m, + qr/^Perfdata *: testdb=.*s warn=3600 crit=864000$/m +); + +# we don't check the [auto][vacuum,analyze]_count here, because we are filtering out +# system tables which were accounted for in the previous test. + +$node->command_checks_all( [ + './check_pgactivity', '--service' => 'last_vacuum', + '--vacuum-table-min-size' => '10kb', + '--username' => $ENV{'USER'} || 'postgres', + '--format' => 'human', + '--dbname' => 'testdb', + '--status-file' => $pga_data, + '--warning' => '1h', + '--critical' => '10d' + ], + 0, + \@stdout, + [ qr/^$/ ], + 'database with two tables, one never vacuumed, filtering out small tables' +); + ### End of tests ### $node->stop( 'immediate' );