From dfdde84cbcf757530addbdb766c6de2d710e3284 Mon Sep 17 00:00:00 2001 From: Jens Wilke Date: Mon, 12 Dec 2022 17:09:59 +0100 Subject: [PATCH 1/3] Add Partman premake check --- check_postgres.pl | 135 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/check_postgres.pl b/check_postgres.pl index 37d334a..37f1d0e 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -202,6 +202,8 @@ 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 --PGBINDIR or --PSQL option when NO_PSQL_OPTION is on}, + 'partman-premake-ok' => q{All premade partitions are present}, + 'partman-conf-tbl' => q{misconfigured in partman.part_config}, 'pgagent-jobs-ok' => q{No failed jobs}, 'pgbouncer-pool' => q{Pool=$1 $2=$3}, 'pgb-backends-mrtg' => q{DB=$1 Max connections=$2}, @@ -1899,6 +1901,7 @@ package check_postgres; new_version_cp => [0, 'Checks if a newer version of check_postgres.pl is available.'], new_version_pg => [0, 'Checks if a newer version of Postgres is available.'], new_version_tnm => [0, 'Checks if a newer version of tail_n_mail is available.'], + partman_premake => [1, 'Checks if premake partitions are in place.'], pgb_pool_cl_active => [1, 'Check the number of active clients in each pgbouncer pool.'], pgb_pool_cl_waiting => [1, 'Check the number of waiting clients in each pgbouncer pool.'], pgb_pool_sv_active => [1, 'Check the number of active server connections in each pgbouncer pool.'], @@ -2735,6 +2738,9 @@ sub finishup { ## Make sure Slony is behaving check_slony_status() if $action eq 'slony_status'; +## Make sure Partman premake is working +check_partman_premake() if $action eq 'partman_premake'; + ## Verify that the pgbouncer settings are what we think they should be check_pgbouncer_checksum() if $action eq 'pgbouncer_checksum'; @@ -6525,6 +6531,133 @@ sub check_pgagent_jobs { return; } +sub check_partman_premake { + + ## Checks if all premade partitions are in place + ## Monthly and daily interval only + ## Supports: Nagios + + my $msg = msg('partman-premake-ok'); + my $found = 0; + my ($warning, $critical) = validate_range + ({ + type => 'integer', # in days + default_warning => '1', + default_critical => '3', + }); + + my $SQL = q{ +SELECT + current_database() as database, + parent_table +FROM ( + SELECT + parent_table, + retention, + partition_interval, + EXTRACT(EPOCH FROM retention::interval) / EXTRACT(EPOCH FROM partition_interval::interval) AS configured_partitions + FROM + partman.part_config) p +WHERE + configured_partitions < 1; +}; + + my $info = run_command($SQL, {regex => qr[\w+], emptyok => 1 } ); + my (@crit,@warn,@ok); + + for $db (@{$info->{db}}) { + my ($maxage,$maxdb) = (0,''); ## used by MRTG only + ROW: for my $r (@{$db->{slurp}}) { + my ($dbname,$parent_table) = ($r->{database},$r->{parent_table}); + $found = 1 if ! $found; + next ROW if skip_item($dbname); + $found = 2; + + $msg = "$dbname=$parent_table " . msg('partman-conf-tbl'); + push @warn => $msg; + }; + }; + + + $SQL = q{ +SELECT + current_database() as database, + a.parent_table, + b.date - a.date::date AS missing_days +FROM +( +SELECT parent_table, date +FROM ( SELECT + i.inhparent::regclass as parent_table, + substring(pg_catalog.pg_get_expr(c.relpartbound, i.inhrelid)::text FROM '%TO __#"_{10}#"%' FOR '#') as date, + rank() OVER (PARTITION BY i.inhparent ORDER BY pg_catalog.pg_get_expr(c.relpartbound, i.inhrelid) DESC) + FROM pg_inherits i + JOIN pg_class c ON c.oid = i.inhrelid +WHERE c.relkind = 'r' + AND pg_catalog.pg_get_expr(c.relpartbound, i.inhrelid) != 'DEFAULT') p +WHERE + p.rank = 1 +) a +JOIN +( +SELECT + parent_table, + (now() + premake * partition_interval::interval)::date +FROM + partman.part_config +) b +ON + a.parent_table::text = b.parent_table::text +WHERE + b.date - a.date::date > 0 +ORDER BY 3, 2 DESC +}; + + $info = run_command($SQL, {regex => qr[\w+], emptyok => 1 } ); + + for $db (@{$info->{db}}) { + my ($maxage,$maxdb) = (0,''); ## used by MRTG only + ROW: for my $r (@{$db->{slurp}}) { + my ($dbname,$parent_table,$missing_days) = ($r->{database},$r->{parent_table},$r->{missing_days}); + $found = 1 if ! $found; + next ROW if skip_item($dbname); + $found = 2; + + $msg = "$dbname=$parent_table ($missing_days)"; + print "$msg"; + $db->{perf} .= sprintf ' %s=%sd;%s;%s', + perfname($dbname), $missing_days, $warning, $critical; + if (length $critical and $missing_days >= $critical) { + push @crit => $msg; + } + elsif (length $warning and $missing_days >= $warning) { + push @warn => $msg; + } + else { + push @ok => $msg; + } + } + if (0 == $found) { + add_ok msg('partman-premake-ok'); + } + elsif (1 == $found) { + add_unknown msg('no-match-db'); + } + elsif (@crit) { + add_critical join ' ' => @crit; + } + elsif (@warn) { + add_warning join ' ' => @warn; + } + else { + add_ok join ' ' => @ok; + } + } + + return; + +} ## end of check_partman_premake + sub check_pgbouncer_checksum { ## Verify the checksum of all pgbouncer settings @@ -11020,6 +11153,8 @@ =head1 HISTORY Fix check_replication_slots on recently promoted servers (Christoph Berg) + Add Partman premake check (Jens Wilke) + =item B Released February 3, 2020 Allow same_schema objects to be included or excluded with --object and --skipobject From 08bc04608e586617cd9158f40e690c9d061d0cc8 Mon Sep 17 00:00:00 2001 From: Jens Wilke Date: Mon, 12 Dec 2022 17:16:16 +0100 Subject: [PATCH 2/3] Add Partman premake check --- check_postgres.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index 37f1d0e..62866ca 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -1901,7 +1901,7 @@ package check_postgres; new_version_cp => [0, 'Checks if a newer version of check_postgres.pl is available.'], new_version_pg => [0, 'Checks if a newer version of Postgres is available.'], new_version_tnm => [0, 'Checks if a newer version of tail_n_mail is available.'], - partman_premake => [1, 'Checks if premake partitions are in place.'], + partman_premake => [1, 'Checks if premake partitions are present.'], pgb_pool_cl_active => [1, 'Check the number of active clients in each pgbouncer pool.'], pgb_pool_cl_waiting => [1, 'Check the number of waiting clients in each pgbouncer pool.'], pgb_pool_sv_active => [1, 'Check the number of active server connections in each pgbouncer pool.'], @@ -6533,7 +6533,7 @@ sub check_pgagent_jobs { sub check_partman_premake { - ## Checks if all premade partitions are in place + ## Checks if all premade partitions are present ## Monthly and daily interval only ## Supports: Nagios From 0477e93553a28fb8ce456f5e15cea14b75e8a511 Mon Sep 17 00:00:00 2001 From: Jens Wilke Date: Mon, 19 Dec 2022 12:03:55 +0100 Subject: [PATCH 3/3] Alert missing range partitioned Tables in part_config --- check_postgres.pl | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index 62866ca..ca1a72d 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -204,6 +204,7 @@ package check_postgres; 'opt-psql-restrict' => q{Cannot use the --PGBINDIR or --PSQL option when NO_PSQL_OPTION is on}, 'partman-premake-ok' => q{All premade partitions are present}, 'partman-conf-tbl' => q{misconfigured in partman.part_config}, + 'partman-conf-mis' => q{missing table in partman.part_config}, 'pgagent-jobs-ok' => q{No failed jobs}, 'pgbouncer-pool' => q{Pool=$1 $2=$3}, 'pgb-backends-mrtg' => q{DB=$1 Max connections=$2}, @@ -6546,7 +6547,46 @@ sub check_partman_premake { default_critical => '3', }); + # check missing Config for range partitioned tables + my $SQL = q{ +SELECT + current_database() AS database, + c.relnamespace::regnamespace || '.' || c.relname AS parent_table +FROM + pg_class c + JOIN pg_partitioned_table t ON t.partrelid = c.oid +WHERE + c.relkind = 'p' + AND t.partstrat = 'r' + AND NOT EXISTS ( + SELECT + 1 + FROM + partman.part_config + WHERE + parent_table = c.relnamespace::regnamespace || '.' || c.relname); +}; + + my $info = run_command($SQL, {regex => qr[\w+], emptyok => 1 } ); + my (@crit,@warn,@ok); + + for $db (@{$info->{db}}) { + my ($maxage,$maxdb) = (0,''); ## used by MRTG only + ROW: for my $r (@{$db->{slurp}}) { + my ($dbname,$parent_table) = ($r->{database},$r->{parent_table}); + $found = 1 if ! $found; + next ROW if skip_item($dbname); + $found = 2; + + $msg = "$dbname=$parent_table " . msg('partman-conf-mis'); + push @crit => $msg; + }; + }; + + # check Config Errors + + $SQL = q{ SELECT current_database() as database, parent_table @@ -6562,8 +6602,7 @@ sub check_partman_premake { configured_partitions < 1; }; - my $info = run_command($SQL, {regex => qr[\w+], emptyok => 1 } ); - my (@crit,@warn,@ok); + $info = run_command($SQL, {regex => qr[\w+], emptyok => 1 } ); for $db (@{$info->{db}}) { my ($maxage,$maxdb) = (0,''); ## used by MRTG only