(plugin) database::postgres - metrics v2 + mode bloat (#3771)
This commit is contained in:
parent
69569136a0
commit
71075fb863
|
@ -27,16 +27,15 @@ use warnings;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my ($class, %options) = @_;
|
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;
|
bless $self, $class;
|
||||||
|
|
||||||
$options{options}->add_options(arguments =>
|
$options{options}->add_options(arguments => {
|
||||||
{
|
'warning:s' => { name => 'warning' },
|
||||||
"warning:s" => { name => 'warning', },
|
'critical:s' => { name => 'critical' },
|
||||||
"critical:s" => { name => 'critical', },
|
'exclude:s' => { name => 'exclude' },
|
||||||
"exclude:s" => { name => 'exclude', },
|
'noidle' => { name => 'noidle' }
|
||||||
"noidle" => { name => 'noidle', },
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
@ -46,22 +45,19 @@ sub check_options {
|
||||||
$self->SUPER::init(%options);
|
$self->SUPER::init(%options);
|
||||||
|
|
||||||
if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) {
|
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}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'.");
|
||||||
$self->{output}->option_exit();
|
$self->{output}->option_exit();
|
||||||
}
|
}
|
||||||
if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) {
|
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}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
|
||||||
$self->{output}->option_exit();
|
$self->{output}->option_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub run {
|
sub run {
|
||||||
my ($self, %options) = @_;
|
my ($self, %options) = @_;
|
||||||
# $options{sql} = sqlmode object
|
|
||||||
$self->{sql} = $options{sql};
|
|
||||||
|
|
||||||
$self->{sql}->connect();
|
$options{sql}->connect();
|
||||||
|
|
||||||
my $noidle = '';
|
my $noidle = '';
|
||||||
if (defined($self->{option_results}->{noidle})) {
|
if (defined($self->{option_results}->{noidle})) {
|
||||||
|
@ -72,51 +68,71 @@ sub run {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my $query = "SELECT COUNT(datid) AS current,
|
my $query = "
|
||||||
(SELECT setting AS mc FROM pg_settings WHERE name = 'max_connections') AS mc,
|
SELECT
|
||||||
d.datname
|
COUNT(datid) AS current,
|
||||||
FROM pg_database d
|
(SELECT setting AS mc FROM pg_settings WHERE name = 'max_connections') AS mc,
|
||||||
LEFT JOIN pg_stat_activity s ON (s.datid = d.oid $noidle)
|
d.datname
|
||||||
GROUP BY d.datname
|
FROM pg_database d
|
||||||
ORDER BY d.datname";
|
LEFT JOIN pg_stat_activity s ON (s.datid = d.oid $noidle)
|
||||||
$self->{sql}->query(query => $query);
|
GROUP BY d.datname
|
||||||
|
ORDER BY d.datname
|
||||||
|
";
|
||||||
|
$options{sql}->query(query => $query);
|
||||||
|
|
||||||
$self->{output}->output_add(severity => 'OK',
|
$self->{output}->output_add(
|
||||||
short_msg => "All client database connections are ok.");
|
severity => 'OK',
|
||||||
|
short_msg => 'All client database connections are ok'
|
||||||
|
);
|
||||||
|
|
||||||
my $database_check = 0;
|
my $database_check = 0;
|
||||||
my $result = $self->{sql}->fetchall_arrayref();
|
my $result = $options{sql}->fetchall_arrayref();
|
||||||
|
|
||||||
foreach my $row (@{$result}) {
|
foreach my $row (@{$result}) {
|
||||||
if (defined($self->{option_results}->{exclude}) && $$row[2] !~ /$self->{option_results}->{exclude}/) {
|
if (defined($self->{option_results}->{exclude}) && $$row[2] !~ /$self->{option_results}->{exclude}/) {
|
||||||
$self->{output}->output_add(long_msg => "Skipping database '" . $$row[2] . '"');
|
$self->{output}->output_add(long_msg => "Skipping database '" . $$row[2] . '"');
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
$database_check++;
|
$database_check++;
|
||||||
my $used = $$row[0];
|
my $used = $row->[0];
|
||||||
my $max_connections = $$row[1];
|
my $max_connections = $row->[1];
|
||||||
my $database_name = $$row[2];
|
my $database_name = $row->[2];
|
||||||
|
|
||||||
my $prct_used = ($used * 100) / $max_connections;
|
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' } ]);
|
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)",
|
$self->{output}->output_add(
|
||||||
$database_name, $prct_used, $used, $max_connections));
|
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)) {
|
if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) {
|
||||||
$self->{output}->output_add(severity => $exit_code,
|
$self->{output}->output_add(
|
||||||
short_msg => sprintf("Database '%s': %.2f%% client connections limit reached (%d of max. %d)",
|
severity => $exit_code,
|
||||||
$database_name, $prct_used, $used, $max_connections));
|
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,
|
$self->{output}->perfdata_add(
|
||||||
value => $used,
|
nlabel => 'database.clients.connected.count',
|
||||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $max_connections, cast_int => 1),
|
instances => $database_name,
|
||||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $max_connections, cast_int => 1),
|
value => $used,
|
||||||
min => 0, max => $max_connections);
|
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) {
|
if ($database_check == 0) {
|
||||||
$self->{output}->output_add(severity => 'UNKNOWN',
|
$self->{output}->output_add(
|
||||||
short_msg => 'No database checked. (permission or a wrong exclude filter)');
|
severity => 'UNKNOWN',
|
||||||
|
short_msg => 'No database checked (permission or a wrong exclude filter)'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{output}->display();
|
$self->{output}->display();
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -25,42 +25,41 @@ use base qw(centreon::plugins::templates::counter);
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
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 {
|
sub prefix_database_output {
|
||||||
my ($self, %options) = @_;
|
my ($self, %options) = @_;
|
||||||
|
|
||||||
return "Database '" . $options{instance_value}->{display} . "' ";
|
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 {
|
sub new {
|
||||||
my ($class, %options) = @_;
|
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;
|
bless $self, $class;
|
||||||
|
|
||||||
$options{options}->add_options(arguments =>
|
$options{options}->add_options(arguments => {
|
||||||
{
|
'filter-database:s' => { name => 'filter_database' }
|
||||||
"filter-database:s" => { name => 'filter_database' },
|
});
|
||||||
});
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +70,7 @@ sub check_options {
|
||||||
|
|
||||||
sub manage_selection {
|
sub manage_selection {
|
||||||
my ($self, %options) = @_;
|
my ($self, %options) = @_;
|
||||||
|
|
||||||
$self->{sql} = $options{sql};
|
$self->{sql} = $options{sql};
|
||||||
$self->{sql}->connect();
|
$self->{sql}->connect();
|
||||||
$self->{sql}->query(query => "SELECT pg_database.datname, pg_database_size(pg_database.datname) FROM pg_database;");
|
$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) {
|
foreach my $row (@$result) {
|
||||||
next if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne ''
|
next if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne ''
|
||||||
&& $$row[0] !~ /$self->{option_results}->{filter_database}/);
|
&& $$row[0] !~ /$self->{option_results}->{filter_database}/);
|
||||||
|
|
||||||
$self->{databases}->{$$row[0]}->{display} = $$row[0];
|
$self->{databases}->{$$row[0]}->{display} = $$row[0];
|
||||||
$self->{databases}->{$$row[0]}->{size} = $$row[1];
|
$self->{databases}->{$$row[0]}->{size} = $$row[1];
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,16 +28,16 @@ use centreon::plugins::statefile;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my ($class, %options) = @_;
|
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;
|
bless $self, $class;
|
||||||
|
|
||||||
$options{options}->add_options(arguments =>
|
$options{options}->add_options(arguments => {
|
||||||
{
|
'warning:s' => { name => 'warning' },
|
||||||
"warning:s" => { name => 'warning', },
|
'critical:s' => { name => 'critical' },
|
||||||
"critical:s" => { name => 'critical', },
|
'lookback' => { name => 'lookback' },
|
||||||
"lookback" => { name => 'lookback', },
|
'exclude:s' => { name => 'exclude' }
|
||||||
"exclude:s" => { name => 'exclude', },
|
});
|
||||||
});
|
|
||||||
$self->{statefile_cache} = centreon::plugins::statefile->new(%options);
|
$self->{statefile_cache} = centreon::plugins::statefile->new(%options);
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
|
@ -48,12 +48,12 @@ sub check_options {
|
||||||
$self->SUPER::init(%options);
|
$self->SUPER::init(%options);
|
||||||
|
|
||||||
if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) {
|
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}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'.");
|
||||||
$self->{output}->option_exit();
|
$self->{output}->option_exit();
|
||||||
}
|
}
|
||||||
if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) {
|
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}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
|
||||||
$self->{output}->option_exit();
|
$self->{output}->option_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{statefile_cache}->check_options(%options);
|
$self->{statefile_cache}->check_options(%options);
|
||||||
|
@ -61,45 +61,44 @@ sub check_options {
|
||||||
|
|
||||||
sub run {
|
sub run {
|
||||||
my ($self, %options) = @_;
|
my ($self, %options) = @_;
|
||||||
# $options{sql} = sqlmode object
|
|
||||||
$self->{sql} = $options{sql};
|
|
||||||
|
|
||||||
$self->{sql}->connect();
|
$options{sql}->connect();
|
||||||
|
|
||||||
$self->{sql}->query(query => q{
|
$options{sql}->query(query => q{
|
||||||
SELECT sd.blks_hit, sd.blks_read, d.datname
|
SELECT sd.blks_hit, sd.blks_read, d.datname
|
||||||
FROM pg_stat_database sd, pg_database d
|
FROM pg_stat_database sd, pg_database d
|
||||||
WHERE d.oid=sd.datid
|
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 $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp');
|
||||||
|
|
||||||
my $database_check = 0;
|
my $database_check = 0;
|
||||||
my $new_datas = {};
|
my $new_datas = {};
|
||||||
$new_datas->{last_timestamp} = time();
|
$new_datas->{last_timestamp} = time();
|
||||||
my $result = $self->{sql}->fetchall_arrayref();
|
my $result = $options{sql}->fetchall_arrayref();
|
||||||
|
|
||||||
$self->{output}->output_add(severity => 'OK',
|
$self->{output}->output_add(
|
||||||
short_msg => "All databases hitratio are ok.");
|
severity => 'OK',
|
||||||
|
short_msg => "All databases hitratio are ok"
|
||||||
|
);
|
||||||
|
|
||||||
foreach my $row (@{$result}) {
|
foreach my $row (@{$result}) {
|
||||||
$new_datas->{$$row[2] . '_blks_hit'} = $$row[0];
|
$new_datas->{$$row[2] . '_blks_hit'} = $row->[0];
|
||||||
$new_datas->{$$row[2] . '_blks_read'} = $$row[1];
|
$new_datas->{$$row[2] . '_blks_read'} = $row->[1];
|
||||||
|
|
||||||
if (defined($self->{option_results}->{exclude}) && $$row[2] !~ /$self->{option_results}->{exclude}/) {
|
if (defined($self->{option_results}->{exclude}) && $row->[2] !~ /$self->{option_results}->{exclude}/) {
|
||||||
$self->{output}->output_add(long_msg => "Skipping database '" . $$row[2] . '"');
|
$self->{output}->output_add(long_msg => "Skipping database '" . $$row[2] . '"');
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $old_blks_hit = $self->{statefile_cache}->get(name => $$row[2] . '_blks_hit');
|
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_read = $self->{statefile_cache}->get(name => $row->[2] . '_blks_read');
|
||||||
|
|
||||||
next if (!defined($old_blks_hit) || !defined($old_blks_read));
|
next if (!defined($old_blks_hit) || !defined($old_blks_read));
|
||||||
$old_blks_hit = 0 if ($$row[0] <= $old_blks_hit);
|
$old_blks_hit = 0 if ($$row[0] <= $old_blks_hit);
|
||||||
$old_blks_read = 0 if ($$row[1] <= $old_blks_read);
|
$old_blks_read = 0 if ($$row[1] <= $old_blks_read);
|
||||||
|
|
||||||
$database_check++;
|
$database_check++;
|
||||||
my %prcts = ();
|
my %prcts = ();
|
||||||
my $total_read_requests = $new_datas->{$$row[2] . '_blks_hit'} - $old_blks_hit;
|
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'});
|
$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' } ]);
|
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%%",
|
$self->{output}->output_add(
|
||||||
$$row[2], $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')})
|
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)) {
|
if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) {
|
||||||
$self->{output}->output_add(severity => $exit_code,
|
$self->{output}->output_add(
|
||||||
short_msg => sprintf("Database '%s' hitratio at %.2f%%",
|
severity => $exit_code,
|
||||||
$$row[2], $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')})
|
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 => '%',
|
$self->{output}->perfdata_add(
|
||||||
value => sprintf("%.2f", $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}),
|
nlabel => 'database.hitratio' . ((defined($self->{option_results}->{lookback})) ? '.delta' : '.average') . '.percentage',
|
||||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
|
unit => '%',
|
||||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
|
instances => $row->[2],
|
||||||
min => 0, max => 100);
|
value => sprintf('%.2f', $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}),
|
||||||
$self->{output}->perfdata_add(label => $$row[2] . '_hitratio' . ((defined($self->{option_results}->{lookback})) ? '_now' : ''), unit => '%',
|
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
|
||||||
value => sprintf("%.2f", $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '_now' : '')}),
|
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
|
||||||
min => 0, max => 100);
|
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);
|
$self->{statefile_cache}->write(data => $new_datas);
|
||||||
if (!defined($old_timestamp)) {
|
if (!defined($old_timestamp)) {
|
||||||
$self->{output}->output_add(severity => 'OK',
|
$self->{output}->output_add(
|
||||||
short_msg => "Buffer creation...");
|
severity => 'OK',
|
||||||
|
short_msg => "Buffer creation..."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defined($old_timestamp) && $database_check == 0) {
|
if (defined($old_timestamp) && $database_check == 0) {
|
||||||
$self->{output}->output_add(severity => 'UNKNOWN',
|
$self->{output}->output_add(
|
||||||
short_msg => 'No database checked. (permission or a wrong exclude filter)');
|
severity => 'UNKNOWN',
|
||||||
|
short_msg => 'No database checked (permission or a wrong exclude filter)'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{output}->display();
|
$self->{output}->display();
|
||||||
$self->{output}->exit();
|
$self->{output}->exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,14 @@ use warnings;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my ($class, %options) = @_;
|
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;
|
bless $self, $class;
|
||||||
|
|
||||||
$options{options}->add_options(arguments =>
|
$options{options}->add_options(arguments => {
|
||||||
{
|
'warning:s' => { name => 'warning', default => '' },
|
||||||
"warning:s" => { name => 'warning', default => ''},
|
'critical:s' => { name => 'critical', default => '' },
|
||||||
"critical:s" => { name => 'critical', default => ''},
|
'exclude:s' => { name => 'exclude' }
|
||||||
"exclude:s" => { name => 'exclude', },
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +45,7 @@ sub check_options {
|
||||||
|
|
||||||
my @warns = split /,/, $self->{option_results}->{warning};
|
my @warns = split /,/, $self->{option_results}->{warning};
|
||||||
my @crits = split /,/, $self->{option_results}->{critical};
|
my @crits = split /,/, $self->{option_results}->{critical};
|
||||||
|
|
||||||
foreach my $val (@warns) {
|
foreach my $val (@warns) {
|
||||||
next if (!defined($val));
|
next if (!defined($val));
|
||||||
my ($label, $value) = split /=/, $val;
|
my ($label, $value) = split /=/, $val;
|
||||||
|
@ -72,26 +71,26 @@ sub check_options {
|
||||||
|
|
||||||
sub run {
|
sub run {
|
||||||
my ($self, %options) = @_;
|
my ($self, %options) = @_;
|
||||||
# $options{sql} = sqlmode object
|
|
||||||
$self->{sql} = $options{sql};
|
|
||||||
|
|
||||||
$self->{sql}->connect();
|
$options{sql}->connect();
|
||||||
|
|
||||||
$self->{sql}->query(query => q{
|
$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
|
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',
|
$self->{output}->output_add(
|
||||||
short_msg => "All databases locks are ok.");
|
severity => 'OK',
|
||||||
|
short_msg => "All databases locks are ok"
|
||||||
|
);
|
||||||
|
|
||||||
my $result = $self->{sql}->fetchall_arrayref();
|
my $result = $options{sql}->fetchall_arrayref();
|
||||||
my $dblocks = {};
|
my $dblocks = {};
|
||||||
foreach my $row (@{$result}) {
|
foreach my $row (@{$result}) {
|
||||||
my ($granted, $mode, $dbname) = ($$row[0], $$row[1], $$row[2]);
|
my ($granted, $mode, $dbname) = ($$row[0], $$row[1], $$row[2]);
|
||||||
if (defined($self->{option_results}->{exclude}) && $dbname !~ /$self->{option_results}->{exclude}/) {
|
if (defined($self->{option_results}->{exclude}) && $dbname !~ /$self->{option_results}->{exclude}/) {
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!defined($dblocks->{$dbname})) {
|
if (!defined($dblocks->{$dbname})) {
|
||||||
$dblocks->{$dbname} = {total => 0, waiting => 0};
|
$dblocks->{$dbname} = {total => 0, waiting => 0};
|
||||||
# Empty. no lock (left join)
|
# 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 $dbname (keys %$dblocks) {
|
||||||
foreach my $locktype (keys %{$dblocks->{$dbname}}) {
|
foreach my $locktype (keys %{$dblocks->{$dbname}}) {
|
||||||
$self->{output}->output_add(long_msg => sprintf("Database '%s' lock '%s': %d",
|
$self->{output}->output_add(
|
||||||
$dbname, $locktype, $dblocks->{$dbname}->{$locktype}));
|
long_msg => sprintf(
|
||||||
my $exit_code = $self->{perfdata}->threshold_check(value => $dblocks->{$dbname}->{$locktype}, threshold => [ { label => 'crit-' . $locktype, 'exit_litteral' => 'critical' }, { label => 'warn-' . $locktype, exit_litteral => 'warning' } ]);
|
"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)) {
|
if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) {
|
||||||
$self->{output}->output_add(severity => $exit_code,
|
$self->{output}->output_add(
|
||||||
short_msg => sprintf("Database '%s' lock '%s': %d",
|
severity => $exit_code,
|
||||||
$dbname, $locktype, $dblocks->{$dbname}->{$locktype}));
|
short_msg => sprintf(
|
||||||
|
"Database '%s' lock '%s': %d",
|
||||||
|
$dbname, $locktype, $dblocks->{$dbname}->{$locktype}
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{output}->perfdata_add(label => $dbname . '_' . $locktype,
|
$self->{output}->perfdata_add(
|
||||||
value => $dblocks->{$dbname}->{$locktype},
|
nlabel => 'database.locks.count',
|
||||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn-' . $locktype),
|
instances => [$dbname, $locktype],
|
||||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit-' . $locktype),
|
value => $dblocks->{$dbname}->{$locktype},
|
||||||
min => 0);
|
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn-' . $locktype),
|
||||||
|
critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit-' . $locktype),
|
||||||
|
min => 0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,15 @@ use warnings;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my ($class, %options) = @_;
|
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;
|
bless $self, $class;
|
||||||
|
|
||||||
$options{options}->add_options(arguments => {
|
$options{options}->add_options(arguments => {
|
||||||
'warning:s' => { name => 'warning' },
|
'warning:s' => { name => 'warning' },
|
||||||
'critical:s' => { name => 'critical' },
|
'critical:s' => { name => 'critical' },
|
||||||
'exclude:s' => { name => 'exclude' },
|
'exclude:s' => { name => 'exclude' },
|
||||||
'exclude-user:s' => { name => 'exclude_user' }
|
'exclude-user:s' => { name => 'exclude_user' },
|
||||||
|
'idle' => { name => 'idle' }
|
||||||
});
|
});
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
|
@ -61,21 +62,27 @@ sub run {
|
||||||
|
|
||||||
my $query;
|
my $query;
|
||||||
if ($options{sql}->is_version_minimum(version => '9.2')) {
|
if ($options{sql}->is_version_minimum(version => '9.2')) {
|
||||||
$query = q{
|
$query = sprintf(
|
||||||
SELECT pg_database.datname, pgsa.datid, pgsa.pid, pgsa.usename, pgsa.client_addr, pgsa.query AS current_query, pgsa.state AS state,
|
q{
|
||||||
CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port,
|
SELECT pg_database.datname, pgsa.datid, pgsa.pid, pgsa.usename, pgsa.client_addr, pgsa.query AS current_query, pgsa.state AS state,
|
||||||
COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds
|
CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port,
|
||||||
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))
|
COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds
|
||||||
ORDER BY pgsa.query_start, pgsa.pid DESC
|
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 {
|
} else {
|
||||||
$query = q{
|
$query = sprintf(
|
||||||
SELECT pg_database.datname, pgsa.datid, pgsa.procpid, pgsa.usename, pgsa.client_addr, pgsa.current_query AS current_query, '' AS state,
|
q{
|
||||||
CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port,
|
SELECT pg_database.datname, pgsa.datid, pgsa.procpid, pgsa.usename, pgsa.client_addr, pgsa.current_query AS current_query, '' AS state,
|
||||||
COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds
|
CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port,
|
||||||
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 '<IDLE>%')
|
COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds
|
||||||
ORDER BY pgsa.query_start, pgsa.procpid DESC
|
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 '<IDLE>%'" : ''
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$options{sql}->query(query => $query);
|
$options{sql}->query(query => $query);
|
||||||
|
@ -114,7 +121,8 @@ ORDER BY pgsa.query_start, pgsa.procpid DESC
|
||||||
|
|
||||||
foreach my $dbname (keys %$dbquery) {
|
foreach my $dbname (keys %$dbquery) {
|
||||||
$self->{output}->perfdata_add(
|
$self->{output}->perfdata_add(
|
||||||
label => $dbname . '_qtime_num',
|
nlabel => 'database.longqueries.count',
|
||||||
|
instances => $dbname,
|
||||||
value => $dbquery->{$dbname}->{total},
|
value => $dbquery->{$dbname}->{total},
|
||||||
min => 0
|
min => 0
|
||||||
);
|
);
|
||||||
|
@ -159,6 +167,10 @@ Filter databases.
|
||||||
|
|
||||||
Filter users.
|
Filter users.
|
||||||
|
|
||||||
|
=item B<--idle>
|
||||||
|
|
||||||
|
Idle queries are counted.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
|
@ -26,106 +26,6 @@ use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use Digest::MD5 qw(md5_hex);
|
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 {
|
sub prefix_global_output {
|
||||||
my ($self, %options) = @_;
|
my ($self, %options) = @_;
|
||||||
|
|
||||||
|
@ -138,13 +38,109 @@ sub prefix_database_output {
|
||||||
return "Database '" . $options{instance_value}->{name} . "' ";
|
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 {
|
sub new {
|
||||||
my ($class, %options) = @_;
|
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;
|
bless $self, $class;
|
||||||
|
|
||||||
$options{options}->add_options(arguments => {
|
$options{options}->add_options(arguments => {
|
||||||
"filter-database:s" => { name => 'filter_database' },
|
'filter-database:s' => { name => 'filter_database' }
|
||||||
});
|
});
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
|
@ -156,34 +152,34 @@ sub manage_selection {
|
||||||
$self->{database} = {};
|
$self->{database} = {};
|
||||||
$self->{global} = { commit => 0, rollback => 0, insert => 0, update => 0, delete => 0 };
|
$self->{global} = { commit => 0, rollback => 0, insert => 0, update => 0, delete => 0 };
|
||||||
my $query = q{
|
my $query = q{
|
||||||
SELECT d.datname as name, pg_stat_get_db_xact_commit(d.oid) as commit,
|
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_db_xact_rollback(d.oid) as rollback,
|
||||||
pg_stat_get_tuples_inserted(d.oid) as insert,
|
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
|
pg_stat_get_tuples_updated(d.oid) as update, pg_stat_get_tuples_updated(d.oid) as delete
|
||||||
FROM pg_database d;
|
FROM pg_database d;
|
||||||
};
|
};
|
||||||
$options{sql}->connect();
|
$options{sql}->connect();
|
||||||
$options{sql}->query(query => $query);
|
$options{sql}->query(query => $query);
|
||||||
|
|
||||||
while ((my $row = $options{sql}->fetchrow_hashref())) {
|
while ((my $row = $options{sql}->fetchrow_hashref())) {
|
||||||
if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' &&
|
if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' &&
|
||||||
$row->{name} !~ /$self->{option_results}->{filter_database}/) {
|
$row->{name} !~ /$self->{option_results}->{filter_database}/) {
|
||||||
$self->{output}->output_add(long_msg => "skipping '" . $row->{name} . "': no matching filter.");
|
$self->{output}->output_add(long_msg => "skipping '" . $row->{name} . "': no matching filter.");
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{database}->{$row->{name}} = {%$row};
|
$self->{database}->{ $row->{name} } = $row;
|
||||||
foreach (keys %{$self->{global}}) {
|
foreach (keys %{$self->{global}}) {
|
||||||
$self->{global}->{$_} += $row->{$_};
|
$self->{global}->{$_} += $row->{$_};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scalar(keys %{$self->{database}}) <= 0) {
|
if (scalar(keys %{$self->{database}}) <= 0) {
|
||||||
$self->{output}->add_option_msg(short_msg => "No database found.");
|
$self->{output}->add_option_msg(short_msg => "No database found.");
|
||||||
$self->{output}->option_exit();
|
$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_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'));
|
(defined($self->{option_results}->{filter_database}) ? md5_hex($self->{option_results}->{filter_database}) : md5_hex('all'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,14 +28,13 @@ use Time::HiRes;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my ($class, %options) = @_;
|
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;
|
bless $self, $class;
|
||||||
|
|
||||||
$options{options}->add_options(arguments =>
|
$options{options}->add_options(arguments => {
|
||||||
{
|
'warning:s' => { name => 'warning' },
|
||||||
"warning:s" => { name => 'warning', },
|
'critical:s' => { name => 'critical' }
|
||||||
"critical:s" => { name => 'critical', },
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
@ -45,42 +44,51 @@ sub check_options {
|
||||||
$self->SUPER::init(%options);
|
$self->SUPER::init(%options);
|
||||||
|
|
||||||
if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) {
|
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}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'.");
|
||||||
$self->{output}->option_exit();
|
$self->{output}->option_exit();
|
||||||
}
|
}
|
||||||
if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) {
|
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}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
|
||||||
$self->{output}->option_exit();
|
$self->{output}->option_exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub run {
|
sub run {
|
||||||
my ($self, %options) = @_;
|
my ($self, %options) = @_;
|
||||||
# $options{sql} = sqlmode object
|
|
||||||
$self->{sql} = $options{sql};
|
|
||||||
|
|
||||||
$self->{sql}->connect();
|
$options{sql}->connect();
|
||||||
|
|
||||||
$self->{sql}->query(query => q{
|
$options{sql}->query(query => q{
|
||||||
SELECT extract(epoch FROM now()) AS epok
|
SELECT extract(epoch FROM now()) AS epok
|
||||||
});
|
});
|
||||||
|
|
||||||
my ($result) = $self->{sql}->fetchrow_array();
|
my ($result) = $options{sql}->fetchrow_array();
|
||||||
my $ltime = Time::HiRes::time();
|
my $ltime = Time::HiRes::time();
|
||||||
if (!defined($result)) {
|
if (!defined($result)) {
|
||||||
$self->{output}->add_option_msg(short_msg => "Cannot get server time.");
|
$self->{output}->add_option_msg(short_msg => "Cannot get server time.");
|
||||||
$self->{output}->option_exit();
|
$self->{output}->option_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
my $diff = $result - $ltime;
|
my $diff = $result - $ltime;
|
||||||
my $exit_code = $self->{perfdata}->threshold_check(value => $diff, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]);
|
my $exit_code = $self->{perfdata}->threshold_check(
|
||||||
|
value => $diff,
|
||||||
$self->{output}->output_add(severity => $exit_code,
|
threshold => [
|
||||||
short_msg => sprintf("%.3fs time diff between servers", $diff));
|
{ label => 'critical', exit_litteral => 'critical' },
|
||||||
$self->{output}->perfdata_add(label => 'timediff', unit => 's',
|
{ label => 'warning', exit_litteral => 'warning' }
|
||||||
value => sprintf("%.3f", $diff),
|
]
|
||||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
|
);
|
||||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'));
|
|
||||||
|
$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}->display();
|
||||||
$self->{output}->exit();
|
$self->{output}->exit();
|
||||||
|
|
|
@ -27,7 +27,7 @@ use warnings;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my ($class, %options) = @_;
|
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;
|
bless $self, $class;
|
||||||
|
|
||||||
$options{options}->add_options(arguments => {
|
$options{options}->add_options(arguments => {
|
||||||
|
@ -77,8 +77,9 @@ sub run {
|
||||||
severity => $exit_code,
|
severity => $exit_code,
|
||||||
short_msg => sprintf('Most recent vacuum dates back from %d seconds', $result)
|
short_msg => sprintf('Most recent vacuum dates back from %d seconds', $result)
|
||||||
);
|
);
|
||||||
|
|
||||||
$self->{output}->perfdata_add(
|
$self->{output}->perfdata_add(
|
||||||
label => 'last_vacuum',
|
nlabel => 'vacuum.last_execution.seconds',
|
||||||
value => $result,
|
value => $result,
|
||||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
|
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
|
||||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')
|
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')
|
||||||
|
@ -86,7 +87,7 @@ sub run {
|
||||||
} else {
|
} else {
|
||||||
$self->{output}->output_add(
|
$self->{output}->output_add(
|
||||||
severity => 'UNKNOWN',
|
severity => 'UNKNOWN',
|
||||||
short_msg => 'No vacuum performed on this BD yet.'
|
short_msg => 'No vacuum performed'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,11 @@ sub new {
|
||||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||||
bless $self, $class;
|
bless $self, $class;
|
||||||
|
|
||||||
$self->{version} = '0.1';
|
|
||||||
$self->{modes} = {
|
$self->{modes} = {
|
||||||
'backends' => 'database::postgres::mode::backends',
|
'backends' => 'database::postgres::mode::backends',
|
||||||
|
'bloat' => 'database::postgres::mode::bloat',
|
||||||
'collection' => 'centreon::common::protocols::sql::mode::collection',
|
'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',
|
'database-size' => 'database::postgres::mode::databasesize',
|
||||||
'hitratio' => 'database::postgres::mode::hitratio',
|
'hitratio' => 'database::postgres::mode::hitratio',
|
||||||
'locks' => 'database::postgres::mode::locks',
|
'locks' => 'database::postgres::mode::locks',
|
||||||
|
@ -44,7 +44,7 @@ sub new {
|
||||||
'statistics' => 'database::postgres::mode::statistics',
|
'statistics' => 'database::postgres::mode::statistics',
|
||||||
'tablespace' => 'database::postgres::mode::tablespace',
|
'tablespace' => 'database::postgres::mode::tablespace',
|
||||||
'timesync' => 'database::postgres::mode::timesync',
|
'timesync' => 'database::postgres::mode::timesync',
|
||||||
'vacuum' => 'database::postgres::mode::vacuum',
|
'vacuum' => 'database::postgres::mode::vacuum'
|
||||||
};
|
};
|
||||||
|
|
||||||
$self->{sql_modes}->{psqlcmd} = 'database::postgres::psqlcmd';
|
$self->{sql_modes}->{psqlcmd} = 'database::postgres::psqlcmd';
|
||||||
|
|
Loading…
Reference in New Issue