Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,15 @@ COMPATIBILITY
This service supports both "--dbexclude" and "--dbinclude"
parameters. The 'postgres' database and templates are always
excluded.

It also supports a "--exclude REGEX" parameter to exclude relations
matching a regular expression. The regular expression applies to
"database.schema_name.relation_name". This enables you to filter
either on a relation name for all schemas and databases, on a
qualified named relation (schema + relation) for all databases or on
a qualified named relation in only one database.

You can use multiple "--exclude REGEX" parameters.

Required privileges: unprivileged role able to log in all databases.

Expand Down Expand Up @@ -756,6 +765,15 @@ COMPATIBILITY
parameters. The 'postgres' database and templates are always
excluded.

It also supports a "--exclude REGEX" parameter to exclude relations
matching a regular expression. The regular expression applies to
"database.schema_name.relation_name". This enables you to filter
either on a relation name for all schemas and databases, on a
qualified named relation (schema + relation) for all databases or on
a qualified named relation in only one database.

You can use multiple "--exclude REGEX" parameters.

Required privileges: unprivileged role able to log in all databases.

locks (all)
Expand Down
103 changes: 82 additions & 21 deletions check_pgactivity
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ Repeat this option as many time as needed.
See C<--dbinclude> as well. If a database match both dbexclude and
dbinclude arguments, it is excluded.


=item B<--dbinclude> REGEXP

Some services automatically check all the databases of your
Expand Down Expand Up @@ -511,7 +512,9 @@ my %args = (
'dump-bin-file' => undef,
'format' => 'nagios',
'uid' => undef,
'with-hugepages' => undef
'with-hugepages' => undef,
'schexclude' => undef,
'relexclude' => undef
);

# Set name of the program without path*
Expand Down Expand Up @@ -5149,7 +5152,7 @@ sub check_is_replay_paused {
# Agnostic check vacuum or analyze sub
# FIXME: we can certainly do better about temp tables
sub check_last_maintenance {
my $rs;
my @rs;
my $c_limit;
my $w_limit;
my @perfdata;
Expand Down Expand Up @@ -5182,12 +5185,16 @@ sub check_last_maintenance {
$w_limit = get_time $args{'warning'};

my %queries = (
# 1st field: oldest known maintenance on a table
# 1st field: is the instance in recovery
# 2nd field: current database
# 3nd field: namespace
# 4nd filed: relation
# 5th field: oldest known maintenance on a table
# -inf if a table never had maintenance
# NaN if nothing found or secondary
# 2nd field: total number of maintenance
# 3nd field: total number of auto-maintenance
# 4th field: hash(insert||update||delete||thresholds) to avoid
# NaN if nothing found
# 6th field: total number of maintenance
# 7th field: total number of auto-maintenance
# 8th field: hash(insert||update||delete||thresholds) to avoid
# useless alerts when there is no write activity (if
# thresholds do not change)
#
Expand All @@ -5196,6 +5203,9 @@ sub check_last_maintenance {
$PG_VERSION_82 => qq{
SELECT
false AS is_in_recovery,
current_database(),
schemaname,
relname,
coalesce(max(
coalesce(extract(epoch FROM
current_timestamp -
Expand All @@ -5209,12 +5219,16 @@ sub check_last_maintenance {
||'$c_limit $w_limit'))
FROM pg_stat_user_tables
WHERE schemaname NOT LIKE 'pg_temp_%'
GROUP BY schemaname,relname
},
# Starting with 8.3, we can check database activity from
# pg_stat_database
$PG_VERSION_83 => qq{
SELECT
false AS is_in_recovery,
current_database(),
schemaname,
relname,
coalesce(max(
coalesce(extract(epoch FROM
current_timestamp -
Expand All @@ -5230,12 +5244,16 @@ sub check_last_maintenance {
FROM pg_stat_user_tables
WHERE schemaname NOT LIKE 'pg_temp_%'
AND schemaname NOT LIKE 'pg_toast_temp_%'
GROUP BY schemaname,relname
},
# Starting with 9.0, we can check database status
# (primary or secondary)
$PG_VERSION_90 => qq{
SELECT
pg_is_in_recovery()::int AS is_in_recovery,
current_database(),
schemaname,
relname,
CASE WHEN NOT pg_is_in_recovery() THEN
coalesce(max(
coalesce(extract(epoch FROM
Expand All @@ -5253,11 +5271,15 @@ sub check_last_maintenance {
FROM pg_stat_user_tables
WHERE schemaname NOT LIKE 'pg_temp_%'
AND schemaname NOT LIKE 'pg_toast_temp_%'
GROUP BY schemaname,relname
},
# Starting with 9.1, we can add the analyze/vacuum counts
$PG_VERSION_91 => qq{
SELECT
pg_is_in_recovery()::int AS is_in_recovery,
current_database(),
schemaname,
a.relname,
CASE WHEN NOT pg_is_in_recovery() THEN
coalesce(max(
coalesce(extract(epoch FROM
Expand Down Expand Up @@ -5288,6 +5310,7 @@ sub check_last_maintenance {
AND schemaname NOT LIKE 'pg_toast_temp_%'
AND (('${type}' = 'vacuum' AND relkind <> 'p') -- partitioned table do not have last_* information
OR ('${type}' = 'analyze'))
GROUP BY schemaname, a.relname
}
);

Expand Down Expand Up @@ -5315,30 +5338,50 @@ sub check_last_maintenance {

LOOP_DB: foreach my $db (@all_db) {
my @perf;
my $rs;
my @rs;
my $maintenance;
my $maintenance_count = 0;
my $maintenance_count_auto = 0;
my $maintenance_max = -1;
my $maintenance_hash = 'null';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the proper way to specify this.
@ioguix ?


next LOOP_DB if grep { $db =~ /$_/ } @dbexclude;
next LOOP_DB if @dbinclude and not grep { $db =~ /$_/ } @dbinclude;

$dbchecked++;

$rs = query_ver( $hosts[0], %queries, $db )->[0];

@rs = @{ query_ver( $hosts[0], %queries, $db ) };
$db =~ s/=//g;

# Note: if @rs is empty $rs[0][0] is undef and the boolean test is false
# we check if scalar as lines otherwise $rs[0][0] will create it
return status_unknown( $me,
[ "Server is no primary." ]
) if $rs->[0];
) if scalar @rs and $rs[0][0];

MAINTENANCE_LOOP: foreach my $maintenance (@rs) {

foreach my $exclude_re ( @{ $args{'exclude'} } ) {
next MAINTENANCE_LOOP if "$maintenance->[1].$maintenance->[2].$maintenance->[3]" =~ m/$exclude_re/;
}

push @perfdata => [ $db, $rs->[1], 's', $w_limit, $c_limit ];
$maintenance_count += $maintenance->[5];
$maintenance_count_auto += $maintenance->[6];
$maintenance_hash = $maintenance->[7];
if ( $maintenance->[4] gt $maintenance_max ) {
$maintenance_max = $maintenance->[4];
}

}
push @perfdata => [ $db, $maintenance_max, 's', $w_limit, $c_limit ];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When maintenance_max=Infinity we display Infinitys.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be fixed. Can you fix this @SkyMarshall939 ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell, this hasn't been fixed. Or is it?

FWIW, next release will be on February 12th. It would be great if this PR could be merged before the release happens.


$new_counts{$db} = [ $rs->[2], $rs->[3] ];
$new_counts{$db} = [ $maintenance_count, $maintenance_count_auto ];

if ( exists $counts{$db} ) {

if ($hosts[0]->{'version_num'} >= $PG_VERSION_91 ) {
my $delta = $rs->[2] - $counts{$db}[0];
my $delta_auto = $rs->[3] - $counts{$db}[1];
my $delta = $maintenance_count - $counts{$db}[0];
my $delta_auto = $maintenance_count_auto - $counts{$db}[1];

push @perfdata => (
[ "$db $type", $delta ],
Expand All @@ -5347,25 +5390,25 @@ LOOP_DB: foreach my $db (@all_db) {
}

# avoid alerts if no write activity since last call
if ( defined $counts{$db}[2] and $counts{$db}[2] eq $rs->[3] ) {
if ( defined $counts{$db}[2] and $counts{$db}[2] eq $maintenance_hash ) {
# keep old hashed status for this database
$new_counts{$db}[2] = $counts{$db}[2];
next LOOP_DB;
}
}

if ( $rs->[1] >= $c_limit ) {
push @msg_crit => "$db: " . to_interval($rs->[1]);
if ( $maintenance_max >= $c_limit ) {
push @msg_crit => "$db: " . to_interval($maintenance_max);
next LOOP_DB;
}

if ( $rs->[1] >= $w_limit ) {
push @msg_warn => "$db: " . to_interval($rs->[1]);
if ( $maintenance_max >= $w_limit ) {
push @msg_warn => "$db: " . to_interval($maintenance_max);
next LOOP_DB;
}

# iif everything is OK, save the current hashed status for this database
$new_counts{$db}[2] = $rs->[4];
$new_counts{$db}[2] = $maintenance_hash ;
}

save $hosts[0], "${type}_counts", \%new_counts, $args{'status-file'};
Expand Down Expand Up @@ -5406,6 +5449,15 @@ raise any alerts, unless you change a threshold.
This service supports both C<--dbexclude> and C<--dbinclude> parameters.
The 'postgres' database and templates are always excluded.

This service supports a C<--exclude REGEX> parameter to exclude relations
matching a regular expression. The regular expression applies to
"database.schema_name.relation_name". This enables you to filter either on a
relation name for all schemas and databases, on a qualified named relation
(schema + relation) for all databases or on a qualified named relation in
only one database.

You can use multiple C<--exclude REGEX> parameters.

Required privileges: unprivileged role able to log in all databases.

=cut
Expand Down Expand Up @@ -5442,6 +5494,15 @@ raise any alerts, unless you change a threshold.
This service supports both C<--dbexclude> and C<--dbinclude> parameters.
The 'postgres' database and templates are always excluded.

This service supports a C<--exclude REGEX> parameter to exclude relations
matching a regular expression. The regular expression applies to
"database.schema_name.relation_name". This enables you to filter either on a
relation name for all schemas and databases, on a qualified named relation
(schema + relation) for all databases or on a qualified named relation in
only one database.

You can use multiple C<--exclude REGEX> parameters.

Required privileges: unprivileged role able to log in all databases.

=cut
Expand Down