From 71075fb86355641a2524abffd4c896672e8999cb Mon Sep 17 00:00:00 2001 From: qgarnier Date: Mon, 11 Jul 2022 14:30:03 +0200 Subject: [PATCH] (plugin) database::postgres - metrics v2 + mode bloat (#3771) --- .../database/postgres/mode/backends.pm | 110 +++++---- .../database/postgres/mode/bloat.pm | 228 ++++++++++++++++++ .../database/postgres/mode/connectiontime.pm | 56 +++++ .../database/postgres/mode/databasesize.pm | 55 +++-- .../database/postgres/mode/hitratio.pm | 127 +++++----- .../database/postgres/mode/locks.pm | 79 +++--- .../database/postgres/mode/querytime.pm | 46 ++-- .../database/postgres/mode/statistics.pm | 222 +++++++++-------- .../database/postgres/mode/timesync.pm | 62 ++--- .../database/postgres/mode/vacuum.pm | 7 +- centreon-plugins/database/postgres/plugin.pm | 6 +- 11 files changed, 673 insertions(+), 325 deletions(-) create mode 100644 centreon-plugins/database/postgres/mode/bloat.pm create mode 100644 centreon-plugins/database/postgres/mode/connectiontime.pm diff --git a/centreon-plugins/database/postgres/mode/backends.pm b/centreon-plugins/database/postgres/mode/backends.pm index c851a0b54..aabca7a7d 100644 --- a/centreon-plugins/database/postgres/mode/backends.pm +++ b/centreon-plugins/database/postgres/mode/backends.pm @@ -27,16 +27,15 @@ use warnings; sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; - - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - "exclude:s" => { name => 'exclude', }, - "noidle" => { name => 'noidle', }, - }); + + $options{options}->add_options(arguments => { + 'warning:s' => { name => 'warning' }, + 'critical:s' => { name => 'critical' }, + 'exclude:s' => { name => 'exclude' }, + 'noidle' => { name => 'noidle' } + }); return $self; } @@ -46,22 +45,19 @@ sub check_options { $self->SUPER::init(%options); if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); - $self->{output}->option_exit(); + $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); + $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); - $self->{output}->option_exit(); + $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); + $self->{output}->option_exit(); } - } sub run { my ($self, %options) = @_; - # $options{sql} = sqlmode object - $self->{sql} = $options{sql}; - $self->{sql}->connect(); + $options{sql}->connect(); my $noidle = ''; if (defined($self->{option_results}->{noidle})) { @@ -72,51 +68,71 @@ sub run { } } - my $query = "SELECT COUNT(datid) AS current, - (SELECT setting AS mc FROM pg_settings WHERE name = 'max_connections') AS mc, - d.datname -FROM pg_database d -LEFT JOIN pg_stat_activity s ON (s.datid = d.oid $noidle) -GROUP BY d.datname -ORDER BY d.datname"; - $self->{sql}->query(query => $query); + my $query = " + SELECT + COUNT(datid) AS current, + (SELECT setting AS mc FROM pg_settings WHERE name = 'max_connections') AS mc, + d.datname + FROM pg_database d + LEFT JOIN pg_stat_activity s ON (s.datid = d.oid $noidle) + GROUP BY d.datname + ORDER BY d.datname + "; + $options{sql}->query(query => $query); - $self->{output}->output_add(severity => 'OK', - short_msg => "All client database connections are ok."); + $self->{output}->output_add( + severity => 'OK', + short_msg => 'All client database connections are ok' + ); my $database_check = 0; - my $result = $self->{sql}->fetchall_arrayref(); - + my $result = $options{sql}->fetchall_arrayref(); + foreach my $row (@{$result}) { if (defined($self->{option_results}->{exclude}) && $$row[2] !~ /$self->{option_results}->{exclude}/) { $self->{output}->output_add(long_msg => "Skipping database '" . $$row[2] . '"'); next; - } - + } + $database_check++; - my $used = $$row[0]; - my $max_connections = $$row[1]; - my $database_name = $$row[2]; + my $used = $row->[0]; + my $max_connections = $row->[1]; + my $database_name = $row->[2]; my $prct_used = ($used * 100) / $max_connections; - my $exit_code = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->output_add(long_msg => sprintf("Database '%s': %.2f%% client connections limit reached (%d of max. %d)", - $database_name, $prct_used, $used, $max_connections)); + my $exit_code = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); + $self->{output}->output_add( + long_msg => sprintf( + "Database '%s': %.2f%% client connections limit reached (%d of max. %d)", + $database_name, $prct_used, $used, $max_connections + ) + ); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("Database '%s': %.2f%% client connections limit reached (%d of max. %d)", - $database_name, $prct_used, $used, $max_connections)); + $self->{output}->output_add( + severity => $exit_code, + short_msg => sprintf( + "Database '%s': %.2f%% client connections limit reached (%d of max. %d)", + $database_name, $prct_used, $used, $max_connections + ) + ); } - $self->{output}->perfdata_add(label => 'connections_' . $database_name, - value => $used, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $max_connections, cast_int => 1), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $max_connections, cast_int => 1), - min => 0, max => $max_connections); + $self->{output}->perfdata_add( + nlabel => 'database.clients.connected.count', + instances => $database_name, + value => $used, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $max_connections, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $max_connections, cast_int => 1), + min => 0, + max => $max_connections + ); } + if ($database_check == 0) { - $self->{output}->output_add(severity => 'UNKNOWN', - short_msg => 'No database checked. (permission or a wrong exclude filter)'); + $self->{output}->output_add( + severity => 'UNKNOWN', + short_msg => 'No database checked (permission or a wrong exclude filter)' + ); } $self->{output}->display(); diff --git a/centreon-plugins/database/postgres/mode/bloat.pm b/centreon-plugins/database/postgres/mode/bloat.pm new file mode 100644 index 000000000..3e01e4672 --- /dev/null +++ b/centreon-plugins/database/postgres/mode/bloat.pm @@ -0,0 +1,228 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package database::postgres::mode::bloat; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub prefix_database_output { + my ($self, %options) = @_; + + return "Database '" . $options{instance} . "' "; +} + +sub database_long_output { + my ($self, %options) = @_; + + return "checking database '" . $options{instance} . "'"; +} + +sub prefix_table_output { + my ($self, %options) = @_; + + return "table '" . $options{instance} . "' "; +} + +sub prefix_index_output { + my ($self, %options) = @_; + + return "index '" . $options{instance} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'databases', type => 3, cb_prefix_output => 'prefix_database_output', cb_long_output => 'database_long_output', indent_long_output => ' ', + message_multiple => 'All tables and indexes are ok', + group => [ + { name => 'tables', display_long => 1, cb_prefix_output => 'prefix_table_output', + message_multiple => 'all tables are ok', type => 1, skipped_code => { -10 => 1 } }, + { name => 'indexes', display_long => 1, cb_prefix_output => 'prefix_index_output', + message_multiple => 'all indexes are ok', type => 1, skipped_code => { -10 => 1 } } + ] + } + ]; + + $self->{maps_counters}->{tables} = [ + { label => 'table-usage', nlabel => 'table.space.usage.bytes', set => { + key_values => [ { name => 'used' } ], + output_template => 'used: %s %s', + output_change_bytes => 1, + perfdatas => [ + { template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } + ] + } + }, + { label => 'table-free', nlabel => 'table.space.free.bytes', set => { + key_values => [ { name => 'free' } ], + output_template => 'free: %s %s', + output_change_bytes => 1, + perfdatas => [ + { template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } + ] + } + }, + { label => 'table-dead-tuple', nlabel => 'table.dead_tuple.bytes', set => { + key_values => [ { name => 'dead_tuple_len' } ], + output_template => 'dead tuple: %s %s', + output_change_bytes => 1, + perfdatas => [ + { template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } + ] + } + } + ]; + + $self->{maps_counters}->{indexes} = [ + { label => 'index-usage', nlabel => 'index.space.usage.bytes', set => { + key_values => [ { name => 'used' } ], + output_template => 'used: %s %s', + output_change_bytes => 1, + perfdatas => [ + { template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } + ] + } + }, + { label => 'index-leaf-density', nlabel => 'table.leaf_density.percentage', set => { + key_values => [ { name => 'avg_leaf_density' } ], + output_template => 'average leaf density: %.2f %%', + perfdatas => [ + { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-table:s' => { name => 'filter_table' }, + 'filter-index:s' => { name => 'filter_index' }, + 'filter-size:s' => { name => 'filter_size' } + }); + + return $self; +} + +sub add_tables { + my ($self, %options) = @_; + + $options{sql}->query(query => qq{ + SELECT current_database() as dbname, relname, (pgstattuple(oid)).* from pg_class where relkind IN ('r', 'm') AND relpersistence <> 't' + }); + + while (my $row = $options{sql}->fetchrow_hashref()) { + $self->{databases}->{ $row->{dbname} } = { tables => {}, indexes => {} } + if (!defined($self->{databases}->{ $row->{dbname} })); + + if (defined($self->{option_results}->{filter_table}) && $self->{option_results}->{filter_table} ne '' && + $row->{relname} !~ /$self->{option_results}->{filter_table}/) { + $self->{output}->output_add(long_msg => "skipping '" . $row->{relname} . "': no matching filter.", debug => 1); + next + } + next if (defined($self->{option_results}->{filter_size}) && $self->{option_results}->{filter_size} =~ /^\d+$/ && + $row->{table_len} < $self->{option_results}->{filter_size}); + + $self->{databases}->{ $row->{dbname} }->{tables}->{ $row->{relname} } = { + used => $row->{table_len}, + free => $row->{free_space}, + dead_tuple_len => $row->{dead_tuple_len} + }; + } +} + +sub add_indexes { + my ($self, %options) = @_; + + $options{sql}->query(query => qq{ + SELECT current_database() as dbname, relname, (pgstatindex(oid)).* from pg_class where relkind = 'i' AND relpersistence <> 't' + }); + + while (my $row = $options{sql}->fetchrow_hashref()) { + $self->{databases}->{ $row->{dbname} } = { tables => {}, indexes => {} } + if (!defined($self->{databases}->{ $row->{dbname} })); + + if (defined($self->{option_results}->{filter_index}) && $self->{option_results}->{filter_index} ne '' && + $row->{relname} !~ /$self->{option_results}->{filter_index}/) { + $self->{output}->output_add(long_msg => "skipping '" . $row->{relname} . "': no matching filter.", debug => 1); + next + } + next if (defined($self->{option_results}->{filter_size}) && $self->{option_results}->{filter_size} =~ /^\d+$/ && + $row->{index_size} < $self->{option_results}->{filter_size}); + + $self->{databases}->{ $row->{dbname} }->{indexes}->{ $row->{relname} } = { + used => $row->{index_size}, + avg_leaf_density => $row->{avg_leaf_density} =~ /^[0-9\.]+$/ ? $row->{avg_leaf_density} : undef + }; + } +} + + +sub manage_selection { + my ($self, %options) = @_; + + $options{sql}->connect(); + + $self->{databases} = {}; + $self->add_tables(sql => $options{sql}); + $self->add_indexes(sql => $options{sql}); +} + +1; + +__END__ + +=head1 MODE + +Check tables and btrees bloat. + +=over 8 + +Filter databases by state. + +=item B<--filter-table> + +Filter tables by name (can be a regexp). + +=item B<--filter-index> + +Filter indexes by name (can be a regexp). + +=item B<--filter-size> + +Filter tables and indexes if size (in bytes) is over X. + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'table-usage', 'table-free', 'table-dead-tuple', +'index-usage', 'index-leaf-density'. + +=back + +=cut diff --git a/centreon-plugins/database/postgres/mode/connectiontime.pm b/centreon-plugins/database/postgres/mode/connectiontime.pm new file mode 100644 index 000000000..24e834bb1 --- /dev/null +++ b/centreon-plugins/database/postgres/mode/connectiontime.pm @@ -0,0 +1,56 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package database::postgres::mode::connectiontime; + +use base qw(centreon::common::protocols::sql::mode::connectiontime); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + return $self; +} + +1; + +__END__ + +=head1 MODE + +Check database connection time. + +=over 8 + +=item B<--warning> + +Threshold warning in milliseconds. + +=item B<--critical> + +Threshold critical in milliseconds. + +=back + +=cut diff --git a/centreon-plugins/database/postgres/mode/databasesize.pm b/centreon-plugins/database/postgres/mode/databasesize.pm index d180ca3b4..0155d4a7e 100644 --- a/centreon-plugins/database/postgres/mode/databasesize.pm +++ b/centreon-plugins/database/postgres/mode/databasesize.pm @@ -25,42 +25,41 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; -sub set_counters { - my ($self, %options) = @_; - - $self->{maps_counters_type} = [ - { name => 'databases', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All databases are ok' }, - ]; - - $self->{maps_counters}->{databases} = [ - { label => 'size', set => { - key_values => [ { name => 'size' }, { name => 'display' } ], - output_template => 'size : %s %s', - output_change_bytes => 1, - perfdatas => [ - { label => 'size', value => 'size', template => '%s', - min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, - ], - } - }, - ]; -} - sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'databases', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All databases are ok' } + ]; + + $self->{maps_counters}->{databases} = [ + { label => 'size', nlabel => 'database.space.usage.bytes', set => { + key_values => [ { name => 'size' }, { name => 'display' } ], + output_template => 'size: %s %s', + output_change_bytes => 1, + perfdatas => [ + { template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' } + ] + } + } + ]; +} + sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; - $options{options}->add_options(arguments => - { - "filter-database:s" => { name => 'filter_database' }, - }); + $options{options}->add_options(arguments => { + 'filter-database:s' => { name => 'filter_database' } + }); + return $self; } @@ -71,7 +70,7 @@ sub check_options { sub manage_selection { my ($self, %options) = @_; - + $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => "SELECT pg_database.datname, pg_database_size(pg_database.datname) FROM pg_database;"); @@ -83,7 +82,7 @@ sub manage_selection { foreach my $row (@$result) { next if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $$row[0] !~ /$self->{option_results}->{filter_database}/); - + $self->{databases}->{$$row[0]}->{display} = $$row[0]; $self->{databases}->{$$row[0]}->{size} = $$row[1]; } diff --git a/centreon-plugins/database/postgres/mode/hitratio.pm b/centreon-plugins/database/postgres/mode/hitratio.pm index 7c8727c5d..255ae4e94 100644 --- a/centreon-plugins/database/postgres/mode/hitratio.pm +++ b/centreon-plugins/database/postgres/mode/hitratio.pm @@ -28,16 +28,16 @@ use centreon::plugins::statefile; sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; - - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - "lookback" => { name => 'lookback', }, - "exclude:s" => { name => 'exclude', }, - }); + + $options{options}->add_options(arguments => { + 'warning:s' => { name => 'warning' }, + 'critical:s' => { name => 'critical' }, + 'lookback' => { name => 'lookback' }, + 'exclude:s' => { name => 'exclude' } + }); + $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; @@ -48,12 +48,12 @@ sub check_options { $self->SUPER::init(%options); if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); - $self->{output}->option_exit(); + $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); + $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); - $self->{output}->option_exit(); + $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); + $self->{output}->option_exit(); } $self->{statefile_cache}->check_options(%options); @@ -61,45 +61,44 @@ sub check_options { sub run { my ($self, %options) = @_; - # $options{sql} = sqlmode object - $self->{sql} = $options{sql}; - $self->{sql}->connect(); - - $self->{sql}->query(query => q{ -SELECT sd.blks_hit, sd.blks_read, d.datname -FROM pg_stat_database sd, pg_database d -WHERE d.oid=sd.datid + $options{sql}->connect(); + + $options{sql}->query(query => q{ + SELECT sd.blks_hit, sd.blks_read, d.datname + FROM pg_stat_database sd, pg_database d + WHERE d.oid=sd.datid }); - $self->{statefile_cache}->read(statefile => 'postgres_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); + $self->{statefile_cache}->read(statefile => 'postgres_' . $self->{mode} . '_' . $options{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); - + my $database_check = 0; my $new_datas = {}; $new_datas->{last_timestamp} = time(); - my $result = $self->{sql}->fetchall_arrayref(); + my $result = $options{sql}->fetchall_arrayref(); - $self->{output}->output_add(severity => 'OK', - short_msg => "All databases hitratio are ok."); - + $self->{output}->output_add( + severity => 'OK', + short_msg => "All databases hitratio are ok" + ); foreach my $row (@{$result}) { - $new_datas->{$$row[2] . '_blks_hit'} = $$row[0]; - $new_datas->{$$row[2] . '_blks_read'} = $$row[1]; - - if (defined($self->{option_results}->{exclude}) && $$row[2] !~ /$self->{option_results}->{exclude}/) { + $new_datas->{$$row[2] . '_blks_hit'} = $row->[0]; + $new_datas->{$$row[2] . '_blks_read'} = $row->[1]; + + if (defined($self->{option_results}->{exclude}) && $row->[2] !~ /$self->{option_results}->{exclude}/) { $self->{output}->output_add(long_msg => "Skipping database '" . $$row[2] . '"'); next; } - my $old_blks_hit = $self->{statefile_cache}->get(name => $$row[2] . '_blks_hit'); - my $old_blks_read = $self->{statefile_cache}->get(name => $$row[2] . '_blks_read'); - + my $old_blks_hit = $self->{statefile_cache}->get(name => $row->[2] . '_blks_hit'); + my $old_blks_read = $self->{statefile_cache}->get(name => $row->[2] . '_blks_read'); + next if (!defined($old_blks_hit) || !defined($old_blks_read)); $old_blks_hit = 0 if ($$row[0] <= $old_blks_hit); $old_blks_read = 0 if ($$row[1] <= $old_blks_read); - + $database_check++; my %prcts = (); my $total_read_requests = $new_datas->{$$row[2] . '_blks_hit'} - $old_blks_hit; @@ -108,36 +107,54 @@ WHERE d.oid=sd.datid $prcts{hitratio} = (($new_datas->{$$row[2] . '_blks_hit'} + + $new_datas->{$$row[2] . '_blks_read'}) == 0) ? 100 : $new_datas->{$$row[2] . '_blks_hit'} * 100 / ($new_datas->{$$row[2] . '_blks_hit'} + $new_datas->{$$row[2] . '_blks_read'}); my $exit_code = $self->{perfdata}->threshold_check(value => $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now' )}, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->output_add(long_msg => sprintf("Database '%s' hitratio at %.2f%%", - $$row[2], $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) - ); + $self->{output}->output_add( + long_msg => sprintf( + "Database '%s' hitratio at %.2f%%", + $row->[2], $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')} + ) + ); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("Database '%s' hitratio at %.2f%%", - $$row[2], $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) - ); + $self->{output}->output_add( + severity => $exit_code, + short_msg => sprintf( + "Database '%s' hitratio at %.2f%%", + $row->[2], $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) + ); } - $self->{output}->perfdata_add(label => $$row[2] . '_hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now'), unit => '%', - value => sprintf("%.2f", $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}), - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), - min => 0, max => 100); - $self->{output}->perfdata_add(label => $$row[2] . '_hitratio' . ((defined($self->{option_results}->{lookback})) ? '_now' : ''), unit => '%', - value => sprintf("%.2f", $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '_now' : '')}), - min => 0, max => 100); + $self->{output}->perfdata_add( + nlabel => 'database.hitratio' . ((defined($self->{option_results}->{lookback})) ? '.delta' : '.average') . '.percentage', + unit => '%', + instances => $row->[2], + value => sprintf('%.2f', $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}), + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), + min => 0, max => 100 + ); + $self->{output}->perfdata_add( + nlabel => 'database.hitratio' . ((defined($self->{option_results}->{lookback})) ? '.average' : '.delta') . '.percentage', + unit => '%', + instances => $row->[2], + value => sprintf('%.2f', $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '_now' : '')}), + min => 0, max => 100 + ); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { - $self->{output}->output_add(severity => 'OK', - short_msg => "Buffer creation..."); + $self->{output}->output_add( + severity => 'OK', + short_msg => "Buffer creation..." + ); } + if (defined($old_timestamp) && $database_check == 0) { - $self->{output}->output_add(severity => 'UNKNOWN', - short_msg => 'No database checked. (permission or a wrong exclude filter)'); + $self->{output}->output_add( + severity => 'UNKNOWN', + short_msg => 'No database checked (permission or a wrong exclude filter)' + ); } - + $self->{output}->display(); $self->{output}->exit(); } diff --git a/centreon-plugins/database/postgres/mode/locks.pm b/centreon-plugins/database/postgres/mode/locks.pm index 144ebd268..60e9bd3ac 100644 --- a/centreon-plugins/database/postgres/mode/locks.pm +++ b/centreon-plugins/database/postgres/mode/locks.pm @@ -27,15 +27,14 @@ use warnings; sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; - - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning', default => ''}, - "critical:s" => { name => 'critical', default => ''}, - "exclude:s" => { name => 'exclude', }, - }); + + $options{options}->add_options(arguments => { + 'warning:s' => { name => 'warning', default => '' }, + 'critical:s' => { name => 'critical', default => '' }, + 'exclude:s' => { name => 'exclude' } + }); return $self; } @@ -46,7 +45,7 @@ sub check_options { my @warns = split /,/, $self->{option_results}->{warning}; my @crits = split /,/, $self->{option_results}->{critical}; - + foreach my $val (@warns) { next if (!defined($val)); my ($label, $value) = split /=/, $val; @@ -72,26 +71,26 @@ sub check_options { sub run { my ($self, %options) = @_; - # $options{sql} = sqlmode object - $self->{sql} = $options{sql}; - $self->{sql}->connect(); + $options{sql}->connect(); - $self->{sql}->query(query => q{ -SELECT granted, mode, datname FROM pg_database d LEFT JOIN pg_locks l ON (d.oid=l.database) WHERE d.datallowconn -}); + $options{sql}->query(query => q{ + SELECT granted, mode, datname FROM pg_database d LEFT JOIN pg_locks l ON (d.oid=l.database) WHERE d.datallowconn + }); - $self->{output}->output_add(severity => 'OK', - short_msg => "All databases locks are ok."); + $self->{output}->output_add( + severity => 'OK', + short_msg => "All databases locks are ok" + ); - my $result = $self->{sql}->fetchall_arrayref(); + my $result = $options{sql}->fetchall_arrayref(); my $dblocks = {}; foreach my $row (@{$result}) { my ($granted, $mode, $dbname) = ($$row[0], $$row[1], $$row[2]); if (defined($self->{option_results}->{exclude}) && $dbname !~ /$self->{option_results}->{exclude}/) { next; } - + if (!defined($dblocks->{$dbname})) { $dblocks->{$dbname} = {total => 0, waiting => 0}; # Empty. no lock (left join) @@ -105,21 +104,37 @@ SELECT granted, mode, datname FROM pg_database d LEFT JOIN pg_locks l ON (d.oid= foreach my $dbname (keys %$dblocks) { foreach my $locktype (keys %{$dblocks->{$dbname}}) { - $self->{output}->output_add(long_msg => sprintf("Database '%s' lock '%s': %d", - $dbname, $locktype, $dblocks->{$dbname}->{$locktype})); - my $exit_code = $self->{perfdata}->threshold_check(value => $dblocks->{$dbname}->{$locktype}, threshold => [ { label => 'crit-' . $locktype, 'exit_litteral' => 'critical' }, { label => 'warn-' . $locktype, exit_litteral => 'warning' } ]); - + $self->{output}->output_add( + long_msg => sprintf( + "Database '%s' lock '%s': %d", + $dbname, $locktype, $dblocks->{$dbname}->{$locktype} + ) + ); + my $exit_code = $self->{perfdata}->threshold_check( + value => $dblocks->{$dbname}->{$locktype}, + threshold => [ + { label => 'crit-' . $locktype, exit_litteral => 'critical' }, + { label => 'warn-' . $locktype, exit_litteral => 'warning' } + ] + ); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("Database '%s' lock '%s': %d", - $dbname, $locktype, $dblocks->{$dbname}->{$locktype})); + $self->{output}->output_add( + severity => $exit_code, + short_msg => sprintf( + "Database '%s' lock '%s': %d", + $dbname, $locktype, $dblocks->{$dbname}->{$locktype} + ) + ); } - - $self->{output}->perfdata_add(label => $dbname . '_' . $locktype, - value => $dblocks->{$dbname}->{$locktype}, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn-' . $locktype), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit-' . $locktype), - min => 0); + + $self->{output}->perfdata_add( + nlabel => 'database.locks.count', + instances => [$dbname, $locktype], + value => $dblocks->{$dbname}->{$locktype}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn-' . $locktype), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit-' . $locktype), + min => 0 + ); } } diff --git a/centreon-plugins/database/postgres/mode/querytime.pm b/centreon-plugins/database/postgres/mode/querytime.pm index 123973f50..6e7576725 100644 --- a/centreon-plugins/database/postgres/mode/querytime.pm +++ b/centreon-plugins/database/postgres/mode/querytime.pm @@ -27,14 +27,15 @@ use warnings; sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'exclude:s' => { name => 'exclude' }, - 'exclude-user:s' => { name => 'exclude_user' } + 'exclude-user:s' => { name => 'exclude_user' }, + 'idle' => { name => 'idle' } }); return $self; @@ -61,21 +62,27 @@ sub run { my $query; if ($options{sql}->is_version_minimum(version => '9.2')) { - $query = q{ -SELECT pg_database.datname, pgsa.datid, pgsa.pid, pgsa.usename, pgsa.client_addr, pgsa.query AS current_query, pgsa.state AS state, - CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port, - COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds -FROM pg_database LEFT JOIN pg_stat_activity pgsa ON pg_database.datname = pgsa.datname AND (pgsa.query_start IS NOT NULL AND (pgsa.state NOT LIKE 'idle%' OR pgsa.state IS NULL)) -ORDER BY pgsa.query_start, pgsa.pid DESC -}; + $query = sprintf( + q{ + SELECT pg_database.datname, pgsa.datid, pgsa.pid, pgsa.usename, pgsa.client_addr, pgsa.query AS current_query, pgsa.state AS state, + CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port, + COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds + FROM pg_database LEFT JOIN pg_stat_activity pgsa ON pg_database.datname = pgsa.datname AND (pgsa.query_start IS NOT NULL AND (%s pgsa.state IS NULL)) + ORDER BY pgsa.query_start, pgsa.pid DESC + }, + !defined($self->{option_results}->{idle}) ? "pgsa.state NOT LIKE 'idle%' OR" : '' + ); } else { - $query = q{ -SELECT pg_database.datname, pgsa.datid, pgsa.procpid, pgsa.usename, pgsa.client_addr, pgsa.current_query AS current_query, '' AS state, - CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port, - COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds -FROM pg_database LEFT JOIN pg_stat_activity pgsa ON pg_database.datname = pgsa.datname AND (pgsa.query_start IS NOT NULL AND current_query NOT LIKE '%') -ORDER BY pgsa.query_start, pgsa.procpid DESC -}; + $query = sprintf( + q{ + SELECT pg_database.datname, pgsa.datid, pgsa.procpid, pgsa.usename, pgsa.client_addr, pgsa.current_query AS current_query, '' AS state, + CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port, + COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds + FROM pg_database LEFT JOIN pg_stat_activity pgsa ON pg_database.datname = pgsa.datname AND (pgsa.query_start IS NOT NULL %s) + ORDER BY pgsa.query_start, pgsa.procpid DESC + }, + !defined($self->{option_results}->{idle}) ? " AND current_query NOT LIKE '%'" : '' + ); } $options{sql}->query(query => $query); @@ -114,7 +121,8 @@ ORDER BY pgsa.query_start, pgsa.procpid DESC foreach my $dbname (keys %$dbquery) { $self->{output}->perfdata_add( - label => $dbname . '_qtime_num', + nlabel => 'database.longqueries.count', + instances => $dbname, value => $dbquery->{$dbname}->{total}, min => 0 ); @@ -159,6 +167,10 @@ Filter databases. Filter users. +=item B<--idle> + +Idle queries are counted. + =back =cut diff --git a/centreon-plugins/database/postgres/mode/statistics.pm b/centreon-plugins/database/postgres/mode/statistics.pm index bcd8a6c3b..6f8e468d5 100644 --- a/centreon-plugins/database/postgres/mode/statistics.pm +++ b/centreon-plugins/database/postgres/mode/statistics.pm @@ -26,106 +26,6 @@ use strict; use warnings; use Digest::MD5 qw(md5_hex); -sub set_counters { - my ($self, %options) = @_; - - $self->{maps_counters_type} = [ - { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, - { name => 'database', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All database statistics are ok' } - ]; - - $self->{maps_counters}->{global} = [ - { label => 'total-commit', nlabel => 'queries.commit.count', set => { - key_values => [ { name => 'commit', diff => 1 } ], - output_template => 'Commit : %s', - perfdatas => [ - { label => 'commit', value => 'commit', template => '%s', min => 0 }, - ], - } - }, - { label => 'total-rollback', nlabel => 'queries.rollback.count', set => { - key_values => [ { name => 'rollback', diff => 1 } ], - output_template => 'Rollback : %s', - perfdatas => [ - { label => 'rollback', value => 'rollback', template => '%s', min => 0 }, - ], - } - }, - { label => 'total-insert', nlabel => 'queries.insert.count', set => { - key_values => [ { name => 'insert', diff => 1 } ], - output_template => 'Insert : %s', - perfdatas => [ - { label => 'insert', value => 'insert', template => '%s', min => 0 }, - ], - } - }, - { label => 'total-update', nlabel => 'queries.update.count', set => { - key_values => [ { name => 'update', diff => 1 } ], - output_template => 'Update : %s', - perfdatas => [ - { label => 'update', value => 'update', template => '%s', min => 0 }, - ], - } - }, - { label => 'total-delete', nlabel => 'queries.delete.count', set => { - key_values => [ { name => 'delete', diff => 1 } ], - output_template => 'Delete : %s', - perfdatas => [ - { label => 'delete', value => 'delete', template => '%s', min => 0 }, - ], - } - }, - ]; - - $self->{maps_counters}->{database} = [ - { label => 'commit', nlabel => 'queries.commit.count', set => { - key_values => [ { name => 'commit', diff => 1 }, { name => 'name' }, ], - output_template => 'Commit : %s', - perfdatas => [ - { label => 'commit', value => 'commit', template => '%s', - min => 0, label_extra_instance => 1, instance_use => 'name' }, - ], - } - }, - { label => 'rollback', nlabel => 'queries.rollback.count', set => { - key_values => [ { name => 'rollback', diff => 1 }, { name => 'name' }, ], - output_template => 'Rollback : %s', - perfdatas => [ - { label => 'rollback', value => 'rollback', template => '%s', - min => 0, label_extra_instance => 1, instance_use => 'name' }, - ], - } - }, - { label => 'insert', nlabel => 'queries.insert.count', set => { - key_values => [ { name => 'insert', diff => 1 }, { name => 'name' }, ], - output_template => 'Insert : %s', - perfdatas => [ - { label => 'insert', value => 'insert', template => '%s', - min => 0, label_extra_instance => 1, instance_use => 'name' }, - ], - } - }, - { label => 'update', nlabel => 'queries.update.count', set => { - key_values => [ { name => 'update', diff => 1 }, { name => 'name' }, ], - output_template => 'Update : %s', - perfdatas => [ - { label => 'update', value => 'update', template => '%s', - min => 0, label_extra_instance => 1, instance_use => 'name' }, - ], - } - }, - { label => 'delete', nlabel => 'queries.delete.count', set => { - key_values => [ { name => 'delete', diff => 1 }, { name => 'name' }, ], - output_template => 'Delete : %s', - perfdatas => [ - { label => 'delete', value => 'delete', template => '%s', - min => 0, label_extra_instance => 1, instance_use => 'name' }, - ], - } - }, - ]; -} - sub prefix_global_output { my ($self, %options) = @_; @@ -138,13 +38,109 @@ sub prefix_database_output { return "Database '" . $options{instance_value}->{name} . "' "; } +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, + { name => 'database', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All database statistics are ok' } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'total-commit', nlabel => 'queries.commit.count', set => { + key_values => [ { name => 'commit', diff => 1 } ], + output_template => 'commit: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + }, + { label => 'total-rollback', nlabel => 'queries.rollback.count', set => { + key_values => [ { name => 'rollback', diff => 1 } ], + output_template => 'rollback: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + }, + { label => 'total-insert', nlabel => 'queries.insert.count', set => { + key_values => [ { name => 'insert', diff => 1 } ], + output_template => 'insert: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + }, + { label => 'total-update', nlabel => 'queries.update.count', set => { + key_values => [ { name => 'update', diff => 1 } ], + output_template => 'update: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + }, + { label => 'total-delete', nlabel => 'queries.delete.count', set => { + key_values => [ { name => 'delete', diff => 1 } ], + output_template => 'delete: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + }, + ]; + + $self->{maps_counters}->{database} = [ + { label => 'commit', nlabel => 'queries.commit.count', set => { + key_values => [ { name => 'commit', diff => 1 }, { name => 'name' }, ], + output_template => 'commit: %s', + perfdatas => [ + { template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'name' } + ] + } + }, + { label => 'rollback', nlabel => 'queries.rollback.count', set => { + key_values => [ { name => 'rollback', diff => 1 }, { name => 'name' }, ], + output_template => 'rollback: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' } + ] + } + }, + { label => 'insert', nlabel => 'queries.insert.count', set => { + key_values => [ { name => 'insert', diff => 1 }, { name => 'name' }, ], + output_template => 'insert: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' } + ] + } + }, + { label => 'update', nlabel => 'queries.update.count', set => { + key_values => [ { name => 'update', diff => 1 }, { name => 'name' }, ], + output_template => 'update: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' } + ] + } + }, + { label => 'delete', nlabel => 'queries.delete.count', set => { + key_values => [ { name => 'delete', diff => 1 }, { name => 'name' }, ], + output_template => 'delete: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' } + ] + } + } + ]; +} + sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; - + $options{options}->add_options(arguments => { - "filter-database:s" => { name => 'filter_database' }, + 'filter-database:s' => { name => 'filter_database' } }); return $self; @@ -156,34 +152,34 @@ sub manage_selection { $self->{database} = {}; $self->{global} = { commit => 0, rollback => 0, insert => 0, update => 0, delete => 0 }; my $query = q{ -SELECT d.datname as name, pg_stat_get_db_xact_commit(d.oid) as commit, - pg_stat_get_db_xact_rollback(d.oid) as rollback, - pg_stat_get_tuples_inserted(d.oid) as insert, - pg_stat_get_tuples_updated(d.oid) as update, pg_stat_get_tuples_updated(d.oid) as delete + SELECT d.datname as name, pg_stat_get_db_xact_commit(d.oid) as commit, + pg_stat_get_db_xact_rollback(d.oid) as rollback, + pg_stat_get_tuples_inserted(d.oid) as insert, + pg_stat_get_tuples_updated(d.oid) as update, pg_stat_get_tuples_updated(d.oid) as delete FROM pg_database d; -}; + }; $options{sql}->connect(); $options{sql}->query(query => $query); - + while ((my $row = $options{sql}->fetchrow_hashref())) { if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $row->{name} !~ /$self->{option_results}->{filter_database}/) { $self->{output}->output_add(long_msg => "skipping '" . $row->{name} . "': no matching filter."); next; } - - $self->{database}->{$row->{name}} = {%$row}; + + $self->{database}->{ $row->{name} } = $row; foreach (keys %{$self->{global}}) { $self->{global}->{$_} += $row->{$_}; } } - + if (scalar(keys %{$self->{database}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No database found."); $self->{output}->option_exit(); } - $self->{cache_name} = "postgres_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . + $self->{cache_name} = 'postgres_' . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_database}) ? md5_hex($self->{option_results}->{filter_database}) : md5_hex('all')); } diff --git a/centreon-plugins/database/postgres/mode/timesync.pm b/centreon-plugins/database/postgres/mode/timesync.pm index 1c913e9ca..e02bffaac 100644 --- a/centreon-plugins/database/postgres/mode/timesync.pm +++ b/centreon-plugins/database/postgres/mode/timesync.pm @@ -28,14 +28,13 @@ use Time::HiRes; sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; - - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - }); + + $options{options}->add_options(arguments => { + 'warning:s' => { name => 'warning' }, + 'critical:s' => { name => 'critical' } + }); return $self; } @@ -45,42 +44,51 @@ sub check_options { $self->SUPER::init(%options); if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); - $self->{output}->option_exit(); + $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); + $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); - $self->{output}->option_exit(); + $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); + $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; - # $options{sql} = sqlmode object - $self->{sql} = $options{sql}; - $self->{sql}->connect(); + $options{sql}->connect(); - $self->{sql}->query(query => q{ -SELECT extract(epoch FROM now()) AS epok -}); + $options{sql}->query(query => q{ + SELECT extract(epoch FROM now()) AS epok + }); - my ($result) = $self->{sql}->fetchrow_array(); + my ($result) = $options{sql}->fetchrow_array(); my $ltime = Time::HiRes::time(); if (!defined($result)) { $self->{output}->add_option_msg(short_msg => "Cannot get server time."); $self->{output}->option_exit(); } - + my $diff = $result - $ltime; - my $exit_code = $self->{perfdata}->threshold_check(value => $diff, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("%.3fs time diff between servers", $diff)); - $self->{output}->perfdata_add(label => 'timediff', unit => 's', - value => sprintf("%.3f", $diff), - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); + my $exit_code = $self->{perfdata}->threshold_check( + value => $diff, + threshold => [ + { label => 'critical', exit_litteral => 'critical' }, + { label => 'warning', exit_litteral => 'warning' } + ] + ); + + $self->{output}->output_add( + severity => $exit_code, + short_msg => sprintf("%.3fs time diff between servers", $diff) + ); + $self->{output}->perfdata_add( + nlabel => 'time.offset.seconds', + unit => 's', + value => sprintf('%.3f', $diff), + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') + ); $self->{output}->display(); $self->{output}->exit(); diff --git a/centreon-plugins/database/postgres/mode/vacuum.pm b/centreon-plugins/database/postgres/mode/vacuum.pm index 0d4a54b28..7a59d6196 100644 --- a/centreon-plugins/database/postgres/mode/vacuum.pm +++ b/centreon-plugins/database/postgres/mode/vacuum.pm @@ -27,7 +27,7 @@ use warnings; sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { @@ -77,8 +77,9 @@ sub run { severity => $exit_code, short_msg => sprintf('Most recent vacuum dates back from %d seconds', $result) ); + $self->{output}->perfdata_add( - label => 'last_vacuum', + nlabel => 'vacuum.last_execution.seconds', value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') @@ -86,7 +87,7 @@ sub run { } else { $self->{output}->output_add( severity => 'UNKNOWN', - short_msg => 'No vacuum performed on this BD yet.' + short_msg => 'No vacuum performed' ); } diff --git a/centreon-plugins/database/postgres/plugin.pm b/centreon-plugins/database/postgres/plugin.pm index e11ef6070..becc02811 100644 --- a/centreon-plugins/database/postgres/plugin.pm +++ b/centreon-plugins/database/postgres/plugin.pm @@ -29,11 +29,11 @@ sub new { my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; - $self->{version} = '0.1'; $self->{modes} = { 'backends' => 'database::postgres::mode::backends', + 'bloat' => 'database::postgres::mode::bloat', 'collection' => 'centreon::common::protocols::sql::mode::collection', - 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', + 'connection-time' => 'database::postgres::mode::connectiontime', 'database-size' => 'database::postgres::mode::databasesize', 'hitratio' => 'database::postgres::mode::hitratio', 'locks' => 'database::postgres::mode::locks', @@ -44,7 +44,7 @@ sub new { 'statistics' => 'database::postgres::mode::statistics', 'tablespace' => 'database::postgres::mode::tablespace', 'timesync' => 'database::postgres::mode::timesync', - 'vacuum' => 'database::postgres::mode::vacuum', + 'vacuum' => 'database::postgres::mode::vacuum' }; $self->{sql_modes}->{psqlcmd} = 'database::postgres::psqlcmd';