From 91b31a3888e8c4adc3938c5a7e8c94934767bef5 Mon Sep 17 00:00:00 2001 From: blo Date: Thu, 15 Jan 2026 17:55:22 +0100 Subject: [PATCH 1/4] Setting service warning expiration --- check_pgactivity | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/check_pgactivity b/check_pgactivity index e3261a9..faf7e45 100755 --- a/check_pgactivity +++ b/check_pgactivity @@ -7680,13 +7680,19 @@ Required privileges: unprivileged role. sub check_settings { my $me = 'POSTGRES_SETTINGS'; + my $this_msg; + my $now = gettimeofday(); + my $diag = 0; # Ok my @long_msg; my @hosts; my @rs; my %settings; + my $settings_lastemsg; + my $settings_lastedate; my %new_settings; my $pending_count = 0; my %args = %{ $_[0] }; + my $w_limit; my %queries = ( $PG_VERSION_90 => q{ SELECT coalesce(r.rolname, '*'), coalesce(d.datname, '*'), @@ -7713,12 +7719,15 @@ sub check_settings { ); @hosts = @{ parse_hosts %args }; + $w_limit = get_time $args{'warning'} if (defined $args{'warning'}); is_compat $hosts[0], 'settings', $PG_VERSION_90 or exit 1; @rs = @{ query_ver( $hosts[0], %queries ) }; %settings = %{ load( $hosts[0], 'settings', $args{'status-file'} ) || {} }; + $settings_lastemsg = load( $hosts[0], 'settings_lastemsg', $args{'status-file'} ) || undef; + $settings_lastedate = load( $hosts[0], 'settings_lastedate', $args{'status-file'} ) || undef; # Save settings on the very first call $args{'save'} = 1 unless %settings; @@ -7756,16 +7765,42 @@ PARAM_LOOP: foreach my $row (@rs) { } } + $diag = 2 if scalar @long_msg; # Regular warning + $diag = 1 if $pending_count > 0; # Pending restart + + $this_msg = join('\0', @long_msg); + if ( not defined $settings_lastemsg || not defined $settings_lastedate ) { + $settings_lastemsg = ""; + $settings_lastedate = $now; + } + + if ( $this_msg ne $settings_lastemsg ) { + $settings_lastedate = $now; + $settings_lastemsg = $this_msg; + #FIXME: probably nad since we multiply writes to the state file maybe use a hash after + save $hosts[0], 'settings_lastemsg', $settings_lastemsg, $args{'status-file'}; + save $hosts[0], 'settings_lastedate', $settings_lastedate, $args{'status-file'}; + } else { + my $duration = $now - $settings_lastedate; + + if ( defined $w_limit && $diag eq 2 && $duration >= $w_limit ) { + # Should have been a warning but the warning treshold has expired. + # Pending restart changes are not subject to this expiration. + $diag = 0; + $args{'save'} = 1; + } + } + if ( $args{'save'} ) { save $hosts[0], 'settings', \%new_settings, $args{'status-file'}; return status_ok( $me, [ "Setting saved" ] ) } return status_warning( $me, [ 'Setting changed and pending restart!' ], undef, \@long_msg ) - if $pending_count > 0; + if $diag == 1; return status_warning( $me, [ 'Setting changed!' ], undef, \@long_msg ) - if scalar @long_msg; + if $diag == 2; return status_ok( $me, [ "Setting OK" ] ); } @@ -9763,7 +9798,7 @@ pod2usage( pod2usage( -message => 'FATAL: you must provide both warning and critical thresholds.', -exitval => 127 -) if $args{'service'} !~ m/^(pga_version|minor_version|uptime)$/ and ( +) if $args{'service'} !~ m/^(pga_version|minor_version|uptime|settings)$/ and ( ( defined $args{'critical'} and not defined $args{'warning'} ) or ( not defined $args{'critical'} and defined $args{'warning'} )); From 4c6d3de003c7722fc7ba9801f797c546b0cce848 Mon Sep 17 00:00:00 2001 From: blo Date: Fri, 16 Jan 2026 11:02:37 +0100 Subject: [PATCH 2/4] use a hash to reduces writes in the state file --- check_pgactivity | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/check_pgactivity b/check_pgactivity index faf7e45..d52b11a 100755 --- a/check_pgactivity +++ b/check_pgactivity @@ -7682,11 +7682,12 @@ sub check_settings { my $me = 'POSTGRES_SETTINGS'; my $this_msg; my $now = gettimeofday(); - my $diag = 0; # Ok + my $expected_result = 0; # Ok my @long_msg; my @hosts; my @rs; my %settings; + my %settings_laste; my $settings_lastemsg; my $settings_lastedate; my %new_settings; @@ -7726,8 +7727,7 @@ sub check_settings { @rs = @{ query_ver( $hosts[0], %queries ) }; %settings = %{ load( $hosts[0], 'settings', $args{'status-file'} ) || {} }; - $settings_lastemsg = load( $hosts[0], 'settings_lastemsg', $args{'status-file'} ) || undef; - $settings_lastedate = load( $hosts[0], 'settings_lastedate', $args{'status-file'} ) || undef; + %settings_laste = %{ load( $hosts[0], 'settings_laste', $args{'status-file'} ) || {} }; # Save settings on the very first call $args{'save'} = 1 unless %settings; @@ -7765,28 +7765,25 @@ PARAM_LOOP: foreach my $row (@rs) { } } - $diag = 2 if scalar @long_msg; # Regular warning - $diag = 1 if $pending_count > 0; # Pending restart - + $expected_result = 2 if scalar @long_msg; # Regular warning + $expected_result = 1 if $pending_count > 0; # Pending restart $this_msg = join('\0', @long_msg); - if ( not defined $settings_lastemsg || not defined $settings_lastedate ) { - $settings_lastemsg = ""; - $settings_lastedate = $now; + if ( not defined $settings_laste{'date'} || not defined $settings_laste{'msg'} ) { + $settings_laste{'msg'} = ""; + $settings_laste{'date'} = $now; } - if ( $this_msg ne $settings_lastemsg ) { - $settings_lastedate = $now; - $settings_lastemsg = $this_msg; - #FIXME: probably nad since we multiply writes to the state file maybe use a hash after - save $hosts[0], 'settings_lastemsg', $settings_lastemsg, $args{'status-file'}; - save $hosts[0], 'settings_lastedate', $settings_lastedate, $args{'status-file'}; + if ( $this_msg ne $settings_laste{'msg'} ) { + $settings_laste{'msg'} = $this_msg; + $settings_laste{'date'} = $now; + save $hosts[0], 'settings_laste', \%settings_laste, $args{'status-file'}; } else { - my $duration = $now - $settings_lastedate; + my $duration = $now - $settings_laste{'date'}; - if ( defined $w_limit && $diag eq 2 && $duration >= $w_limit ) { + if ( defined $w_limit && $expected_result eq 2 && $duration >= $w_limit ) { # Should have been a warning but the warning treshold has expired. # Pending restart changes are not subject to this expiration. - $diag = 0; + $expected_result = 0; $args{'save'} = 1; } } @@ -7797,10 +7794,10 @@ PARAM_LOOP: foreach my $row (@rs) { } return status_warning( $me, [ 'Setting changed and pending restart!' ], undef, \@long_msg ) - if $diag == 1; + if $expected_result == 1; return status_warning( $me, [ 'Setting changed!' ], undef, \@long_msg ) - if $diag == 2; + if $expected_result == 2; return status_ok( $me, [ "Setting OK" ] ); } From 02d9afe2aeb2735a06c8cc94aad4e98c910220bc Mon Sep 17 00:00:00 2001 From: blo Date: Fri, 16 Jan 2026 11:08:26 +0100 Subject: [PATCH 3/4] Add documentation --- check_pgactivity | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/check_pgactivity b/check_pgactivity index d52b11a..85d95a9 100755 --- a/check_pgactivity +++ b/check_pgactivity @@ -7670,9 +7670,12 @@ again with the argument C<--save>. No perfdata. -Critical and Warning thresholds are ignored. +The Critical thresholds is ignored. -A Critical is raised if at least one parameter changed. +Warning is raised when the time since configuration change is less than the +warning threshold. Obviously these alerts will disappear from themselves +once enough time has passed. This doesn't apply for configuration changes with +pending restart warnings. Required privileges: unprivileged role. From a5459074d5c4d06152c0c1028673dab33b7bb45d Mon Sep 17 00:00:00 2001 From: blo Date: Sat, 17 Jan 2026 10:23:28 +0100 Subject: [PATCH 4/4] Change the code to appease t/01-settings.t --- check_pgactivity | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/check_pgactivity b/check_pgactivity index 85d95a9..b7607f6 100755 --- a/check_pgactivity +++ b/check_pgactivity @@ -7771,17 +7771,15 @@ PARAM_LOOP: foreach my $row (@rs) { $expected_result = 2 if scalar @long_msg; # Regular warning $expected_result = 1 if $pending_count > 0; # Pending restart $this_msg = join('\0', @long_msg); - if ( not defined $settings_laste{'date'} || not defined $settings_laste{'msg'} ) { - $settings_laste{'msg'} = ""; - $settings_laste{'date'} = $now; - } + $settings_lastemsg = $settings_laste{'msg'} // ""; + $settings_lastedate = $settings_laste{'date'} // $now; - if ( $this_msg ne $settings_laste{'msg'} ) { + if ( $this_msg ne $settings_lastemsg ) { $settings_laste{'msg'} = $this_msg; $settings_laste{'date'} = $now; save $hosts[0], 'settings_laste', \%settings_laste, $args{'status-file'}; } else { - my $duration = $now - $settings_laste{'date'}; + my $duration = $now - $settings_lastedate; if ( defined $w_limit && $expected_result eq 2 && $duration >= $w_limit ) { # Should have been a warning but the warning treshold has expired.