From dc7bf4ccd605c5e1062eee5c8e063530ff2e1d39 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Fri, 7 Aug 2015 10:48:56 +0200 Subject: [PATCH] + Enhance firebird plugin --- database/firebird/mode/iostats.pm | 117 ---------- database/firebird/mode/longqueries.pm | 144 ++++++++++++ database/firebird/mode/memory.pm | 303 ++++++++++++++++---------- database/firebird/mode/pages.pm | 210 ++++++++++++++++++ database/firebird/mode/queries.pm | 40 ++-- database/firebird/mode/slowqueries.pm | 139 ------------ database/firebird/mode/users.pm | 15 +- database/firebird/plugin.pm | 15 +- 8 files changed, 574 insertions(+), 409 deletions(-) delete mode 100644 database/firebird/mode/iostats.pm create mode 100644 database/firebird/mode/longqueries.pm create mode 100644 database/firebird/mode/pages.pm delete mode 100644 database/firebird/mode/slowqueries.pm diff --git a/database/firebird/mode/iostats.pm b/database/firebird/mode/iostats.pm deleted file mode 100644 index 3d5f0f951..000000000 --- a/database/firebird/mode/iostats.pm +++ /dev/null @@ -1,117 +0,0 @@ -# -# Copyright 2015 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::firebird::mode::iostats; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use POSIX; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.0'; - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - }); - - return $self; -} - -sub check_options { - my ($self, %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(); - } - 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(); - } -} - -sub run { - my ($self, %options) = @_; - # $options{sql} = sqlmode object - $self->{sql} = $options{sql}; - - $self->{sql}->connect(); - - if (!($self->{sql}->is_version_minimum(version => '1'))) { - $self->{output}->add_option_msg(short_msg => "Firebird version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.x')."); - $self->{output}->option_exit(); - } - - $self->{sql}->query(query => q{SELECT MON$PAGE_READS,MON$PAGE_WRITES FROM MON$IO_STATS WHERE MON$STAT_GROUP=0;}); - my $result = $self->{sql}->fetchall_arrayref(); - if (!defined($result)) { - $self->{output}->add_option_msg(short_msg => "Cannot get IO Stats."); - $self->{output}->option_exit(); - } - - my $page_reads = $$result[0][0]; - my $page_writes = $$result[0][1]; - - my $exit1 = $self->{perfdata}->threshold_check(value => $page_reads, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - my $exit2 = $self->{perfdata}->threshold_check(value => $page_writes, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2 ]); - - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("I/O stats : %d/%d",$page_writes, $page_reads )); - $self->{output}->perfdata_add(label => 'input', value => $page_writes); - $self->{output}->perfdata_add(label => 'output', value => $page_reads); - - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Check MySQL uptime. - -=over 8 - -=item B<--warning> - -Threshold warning. - -=item B<--critical> - -Threshold critical. - -=item B<--seconds> - -Display uptime in seconds. - -=back - -=cut diff --git a/database/firebird/mode/longqueries.pm b/database/firebird/mode/longqueries.pm new file mode 100644 index 000000000..99d639474 --- /dev/null +++ b/database/firebird/mode/longqueries.pm @@ -0,0 +1,144 @@ +# +# Copyright 2015 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::firebird::mode::longqueries; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "warning:s" => { name => 'warning', }, + "critical:s" => { name => 'critical', }, + "seconds:s" => { name => 'seconds', default => 60 }, + "filter-user:s" => { name => 'filter_user' }, + "filter-state:s" => { name => 'filter_state', default => '^(?!(0)$)' }, + }); + + return $self; +} + +sub check_options { + my ($self, %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(); + } + 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(); + } + if (!defined($self->{option_results}->{seconds}) || $self->{option_results}->{seconds} !~ /^[0-9]+$/) { + $self->{output}->add_option_msg(short_msg => "Please set the option --seconds."); + $self->{output}->option_exit(); + } +} + +sub run { + my ($self, %options) = @_; + # $options{sql} = sqlmode object + $self->{sql} = $options{sql}; + + $self->{sql}->connect(); + + $self->{sql}->query(query => q{SELECT ma.MON$USER as MYUSER, ms.MON$STATE as MYSTATE, ms.MON$SQL_TEXT as MYQUERY, (DATEDIFF(second, timestamp '1/1/1970 00:00:00', ms.MON$TIMESTAMP)) as MYTIME FROM MON$STATEMENTS ms, MON$ATTACHMENTS ma WHERE ms.MON$ATTACHMENT_ID = ma.MON$ATTACHMENT_ID}); + my $long_queries = 0; + my @queries = (); + + while ((my $row = $self->{sql}->fetchrow_hashref())) { + $row->{MYUSER} = centreon::plugins::misc::trim($row->{MYUSER}); + $row->{MYQUERY} = '-' if (!defined($row->{MYQUERY})); + next if (!defined($row->{MYTIME})); + + next if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && + $row->{MYUSER} !~ /$self->{option_results}->{filter_user}/i); + next if (defined($self->{option_results}->{filter_state}) && $self->{option_results}->{filter_state} ne '' && + $row->{MYSTATE} !~ /$self->{option_results}->{filter_state}/i); + if (defined($self->{option_results}->{seconds}) && $self->{option_results}->{seconds} ne '' && (time() - $row->{MYTIME}) >= $self->{option_results}->{seconds}) { + push @queries, { time => time() - $row->{MYTIME}, query => $row->{MYQUERY} }; + $long_queries++; + } + } + + my $exit_code = $self->{perfdata}->threshold_check(value => $long_queries, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); + + $self->{output}->output_add(severity => $exit_code, + short_msg => sprintf("%s queries over %s seconds", + $long_queries, $self->{option_results}->{seconds})); + $self->{output}->perfdata_add(label => 'longqueries', + value => $long_queries, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), + min => 0); + + for (my $i = 0; $i < 10 && $i < scalar(@queries); $i++) { + $queries[$i]->{query} =~ s/\|/-/mg; + $self->{output}->output_add(long_msg => sprintf("[time: %s] [query: %s]", + $queries[$i]->{time}, substr($queries[$i]->{query}, 0, 1024))); + } + + $self->{output}->display(); + $self->{output}->exit(); +} + +1; + +__END__ + +=head1 MODE + +Check current number of long queries on the database (firebird version >= 2.1) + +=over 8 + +=item B<--warning> + +Threshold warning (number of long queries). + +=item B<--critical> + +Threshold critical (number of long queries). + +=item B<--critical> + +Threshold critical (number of long queries). + +=item B<--filter-user> + +Filter by user (can be a regexp). + +=item B<--filter-state> + +Filter by state (can be a regexp. Default: '^(?!(0)$)'). + +=back + +=cut diff --git a/database/firebird/mode/memory.pm b/database/firebird/mode/memory.pm index 56ccc8c9a..e97fddb60 100644 --- a/database/firebird/mode/memory.pm +++ b/database/firebird/mode/memory.pm @@ -24,7 +24,111 @@ use base qw(centreon::plugins::mode); use strict; use warnings; -use DBD::Firebird; +use centreon::plugins::values; + +my $maps_counters = { + global => { + '000_used' => { set => { + key_values => [ { name => 'database_used' }, { name => 'database_allocated' } ], + closure_custom_calc => \&custom_unit_calc, closure_custom_calc_extra_options => { label_ref => 'database' }, + closure_custom_output => \&custom_used_output, + threshold_use => 'prct', + closure_custom_perfdata => \&custom_used_perfdata, + } + }, + '001_attachment' => { set => { + key_values => [ { name => 'attachment_used' }, { name => 'database_allocated' } ], + closure_custom_calc => \&custom_unit_calc, closure_custom_calc_extra_options => { label_ref => 'attachment' }, + closure_custom_output => \&custom_unit_output, + threshold_use => 'prct', + closure_custom_perfdata => \&custom_unit_perfdata, + } + }, + '002_transaction' => { set => { + key_values => [ { name => 'transaction_used' }, { name => 'database_allocated' } ], + closure_custom_calc => \&custom_unit_calc, closure_custom_calc_extra_options => { label_ref => 'transaction' }, + closure_custom_output => \&custom_unit_output, + threshold_use => 'prct', + closure_custom_perfdata => \&custom_unit_perfdata, + } + }, + '003_statement' => { set => { + key_values => [ { name => 'statement_used' }, { name => 'database_allocated' } ], + closure_custom_calc => \&custom_unit_calc, closure_custom_calc_extra_options => { label_ref => 'statement' }, + closure_custom_output => \&custom_unit_output, + threshold_use => 'prct', + closure_custom_perfdata => \&custom_unit_perfdata, + } + }, + '004_call' => { set => { + key_values => [ { name => 'call_used' }, { name => 'database_allocated' } ], + closure_custom_calc => \&custom_unit_calc, closure_custom_calc_extra_options => { label_ref => 'call' }, + closure_custom_output => \&custom_unit_output, + threshold_use => 'prct', + closure_custom_perfdata => \&custom_unit_perfdata, + } + }, + }, +}; + +sub custom_used_output { + my ($self, %options) = @_; + + my $free = $self->{result_values}->{total} - $self->{result_values}->{used}; + my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $free); + my $msg = sprintf("Total: %s Used : %s (%.2f %%) Free : %s (%.2f %%)", + $total_value . ' ' . $total_unit, + $used_value . ' ' . $used_unit, $self->{result_values}->{prct}, + $free_value . ' ' . $free_unit, 100 - $self->{result_values}->{prct}); + return $msg; +} + +sub custom_used_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add(label => 'used', unit => 'B', + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_unit_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add(label => $self->{result_values}->{label}, unit => 'B', + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_unit_output { + my ($self, %options) = @_; + + my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my $msg = sprintf("%s : %s (%.2f %%)", + ucfirst($self->{result_values}->{label}), + $used_value . ' ' . $used_unit, $self->{result_values}->{prct}); + return $msg; +} + +sub custom_unit_calc { + my ($self, %options) = @_; + + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_database_allocated'}; + if ($self->{result_values}->{total} == 0) { + $self->{error_msg} = "skipped"; + return -2; + } + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref} . '_used'}; + $self->{result_values}->{prct} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{label} = $options{extra_options}->{label_ref}; + + return 0; +} sub new { my ($class, %options) = @_; @@ -33,12 +137,25 @@ sub new { $self->{version} = '1.0'; $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - "seconds" => { name => 'seconds', }, + { }); - + + foreach my $key (('global')) { + foreach (keys %{$maps_counters->{$key}}) { + my ($id, $name) = split /_/; + if (!defined($maps_counters->{$key}->{$_}->{threshold}) || $maps_counters->{$key}->{$_}->{threshold} != 0) { + $options{options}->add_options(arguments => { + 'warning-' . $name . ':s' => { name => 'warning-' . $name }, + 'critical-' . $name . ':s' => { name => 'critical-' . $name }, + }); + } + $maps_counters->{$key}->{$_}->{obj} = centreon::plugins::values->new(output => $self->{output}, + perfdata => $self->{perfdata}, + label => $name); + $maps_counters->{$key}->{$_}->{obj}->set(%{$maps_counters->{$key}->{$_}->{set}}); + } + } + return $self; } @@ -46,119 +163,79 @@ sub check_options { my ($self, %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(); - } - 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(); + foreach my $key (('global')) { + foreach (keys %{$maps_counters->{$key}}) { + $maps_counters->{$key}->{$_}->{obj}->init(option_results => $self->{option_results}); + } } } sub run { my ($self, %options) = @_; - # $options{sql} = sqlmode object $self->{sql} = $options{sql}; - $self->{sql}->connect(); - - if (!($self->{sql}->is_version_minimum(version => '1'))) { - $self->{output}->add_option_msg(short_msg => "Firebird version '" . $self->{sql}->{version} . "' is not supported (need version >= '1.x')."); - $self->{output}->option_exit(); - } - - $self->{sql}->query(query => q{SELECT MON$STAT_GROUP,MON$MEMORY_ALLOCATED,MON$MEMORY_USED FROM MON$MEMORY_USAGE}); - my $result = $self->{sql}->fetchall_arrayref(); - if(!defined($result)) { - $self->{output}->add_option_msg(short_msg => "Cannot get memory."); - $self->{output}->opion_exit(); - } - - - my $mem_allocated; - my $attach_used=0; - my $prct_attach=0; - my $trans_used=0; - my $prct_trans; - my $stat_used=0; - my $prct_stat=0; - my $call_used=0; - my $prct_call=0; - my ($total_value, $total_unit)=(0,0); - my ($attach_value, $attach_unit)=(0,0); - my ($trans_value, $trans_unit)=(0,0); - my ($stat_value, $stat_unit)=(0,0); - my ($call_value, $call_unit)= (0,'B'); - - foreach my $row (@$result) { - next if (defined($self->{option_results}->{filter}) && - $$row[0] !~ /$self->{option_results}->{filter}/); - - - - if ($$row[0] == 0) { - $mem_allocated = $$row[1]; - ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $mem_allocated); - - } elsif ($$row[0] ==1) { - $attach_used = $attach_used + $$row[2]; - $prct_attach = $attach_used * 100 / $mem_allocated; - ($attach_value, $attach_unit) = $self->{perfdata}->change_bytes(value => $attach_used); - - } elsif ($$row[0] == 2) { - $trans_used = $trans_used + $$row[2]; - $prct_trans = $trans_used * 100 / $mem_allocated; - ($trans_value, $trans_unit) = $self->{perfdata}->change_bytes(value => $trans_used); - - - } elsif ($$row[0] == 3) { - $stat_used = $stat_used + $$row[2]; - $prct_stat = $stat_used * 100 / $mem_allocated; - ($stat_value, $stat_unit) = $self->{perfdata}->change_bytes(value => $stat_used); - - } elsif ($$row[0] ==4) { - $call_used = $call_used + $$row[2]; - $prct_call = $call_used * 100 / $mem_allocated; - ($call_value, $call_unit) = $self->{perfdata}->change_bytes(value => $call_used); + $self->manage_selection(); + + my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', ''); + my @exits; + + foreach (sort keys %{$maps_counters->{global}}) { + my $obj = $maps_counters->{global}->{$_}->{obj}; + + $obj->set(instance => 'firebird'); + + my ($value_check) = $obj->execute(values => $self->{firebird}); + if ($value_check != 0) { + $long_msg .= $long_msg_append . $obj->output_error(); + $long_msg_append = ', '; + next; } + my $exit2 = $obj->threshold_check(); + push @exits, $exit2; + + my $output = $obj->output(); + $long_msg .= $long_msg_append . $output; + $long_msg_append = ', '; + + if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) { + $short_msg .= $short_msg_append . $output; + $short_msg_append = ', '; + } + + $obj->perfdata(); } - my $mem_used = $attach_used + $trans_used + $stat_used + $call_used; - my $prct_used = $mem_used * 100 / $mem_allocated; - my ($used_value, $used_unit)=$self->{perfdata}->change_bytes(value => $mem_used); - - my $exit = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->perfdata_add(label => "used", unit => 'B', - value => $mem_used, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $mem_allocated, cast_int => 1), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $mem_allocated, cast_int => 1), - min => 0, max => $mem_allocated); - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Memory Allocated %s, Total Used %s (%.2f%%)", - $total_value . " " . $total_unit, - $used_value . " " . $used_unit, $prct_used)); - $self->{output}->output_add(long_msg => sprintf("Attachement Used %s (%.2f%%)", - $attach_value . " " . $attach_unit, $prct_attach)); - $self->{output}->perfdata_add(label => "attachement", unit => 'B', - value => $attach_used); - $self->{output}->output_add(long_msg => sprintf("Transaction Used %s (%.2f%%)", - $trans_value . " " . $trans_unit, $prct_trans)); - $self->{output}->perfdata_add(label => "transaction", unit => 'B', - value => $trans_used); - $self->{output}->output_add(long_msg => sprintf("Statement Used %s (%.2f%%)", - $stat_value . " " . $stat_unit, $prct_stat)); - $self->{output}->perfdata_add(label => "statement", unit => 'B', - value => $stat_used); - $self->{output}->output_add(long_msg => sprintf("Call Used %s (%.2f%%)", - $call_value . " " . $call_unit, $prct_call)); - $self->{output}->perfdata_add(label => "call", unit => 'B', - value => $call_used); + my $exit = $self->{output}->get_most_critical(status => [ @exits ]); + if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { + $self->{output}->output_add(severity => $exit, + short_msg => "Memory $short_msg" + ); + } else { + $self->{output}->output_add(short_msg => "Memory $long_msg"); + } + $self->{output}->display(); $self->{output}->exit(); +} - +sub manage_selection { + my ($self, %options) = @_; + + $self->{sql}->connect(); + $self->{sql}->query(query => q{SELECT MON$STAT_GROUP as MYGROUP, MON$MEMORY_ALLOCATED AS MYTOTAL, MON$MEMORY_USED AS MYUSED FROM MON$MEMORY_USAGE}); + + my %map_group = (0 => 'database', 1 => 'attachment', 2 => 'transaction', 3 => 'statement', 4 => 'call'); + + $self->{firebird} = {}; + while ((my $row = $self->{sql}->fetchrow_hashref())) { + if (!defined($self->{firebird}->{$map_group{$row->{MYGROUP}} . '_used'})) { + $self->{firebird}->{$map_group{$row->{MYGROUP}} . '_used'} = 0; + $self->{firebird}->{$map_group{$row->{MYGROUP}} . '_allocated'} = 0; + } + $self->{firebird}->{$map_group{$row->{MYGROUP}} . '_used'} += $row->{MYUSED}; + $self->{firebird}->{$map_group{$row->{MYGROUP}} . '_allocated'} += $row->{MYTOTAL}; + } } 1; @@ -167,21 +244,21 @@ __END__ =head1 MODE -Check MySQL uptime. +Check memory usage. -=over 8 +=over 8) -=item B<--warning> +=item B<--warning-*> Threshold warning. +Can be: 'used' (%), 'attachment' (%), 'transaction' (%), +'statement' (%), 'call' (%). -=item B<--critical> +=item B<--critical-*> Threshold critical. - -=item B<--seconds> - -Display uptime in seconds. +Can be: 'used' (%), 'attachment' (%), 'transaction' (%), +'statement' (%), 'call' (%). =back diff --git a/database/firebird/mode/pages.pm b/database/firebird/mode/pages.pm new file mode 100644 index 000000000..e81927743 --- /dev/null +++ b/database/firebird/mode/pages.pm @@ -0,0 +1,210 @@ +# +# Copyright 2015 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::firebird::mode::pages; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::values; +use centreon::plugins::statefile; + +my $maps_counters = { + global => { + '000_reads' => { set => { + key_values => [ { name => 'reads', diff => 1 } ], + per_second => 1, + output_template => 'Reads : %.2f', + perfdatas => [ + { label => 'reads', template => '%.2f', value => 'reads_per_second', + unit => '/s', min => 0 }, + ], + } + }, + '001_writes' => { set => { + key_values => [ { name => 'writes', diff => 1 } ], + per_second => 1, + output_template => 'Writes : %.2f', + perfdatas => [ + { label => 'writes', template => '%.2f', value => 'writes_per_second', + unit => '/s', min => 0 }, + ], + } + }, + '002_fetches' => { set => { + key_values => [ { name => 'fetches', diff => 1 } ], + per_second => 1, + output_template => 'Fetches : %.2f', + perfdatas => [ + { label => 'fetches', template => '%.2f', value => 'fetches_per_second', + unit => '/s', min => 0 }, + ], + } + }, + '003_statement' => { set => { + key_values => [ { name => 'marks', diff => 1 } ], + per_second => 1, + output_template => 'Marks : %.2f', + perfdatas => [ + { label => 'marks', template => '%.2f', value => 'marks_per_second', + unit => '/s', min => 0 }, + ], + } + }, + }, +}; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + $self->{statefile_value} = centreon::plugins::statefile->new(%options); + + foreach my $key (('global')) { + foreach (keys %{$maps_counters->{$key}}) { + my ($id, $name) = split /_/; + if (!defined($maps_counters->{$key}->{$_}->{threshold}) || $maps_counters->{$key}->{$_}->{threshold} != 0) { + $options{options}->add_options(arguments => { + 'warning-' . $name . ':s' => { name => 'warning-' . $name }, + 'critical-' . $name . ':s' => { name => 'critical-' . $name }, + }); + } + $maps_counters->{$key}->{$_}->{obj} = centreon::plugins::values->new(statefile => $self->{statefile_value}, + output => $self->{output}, perfdata => $self->{perfdata}, + label => $name); + $maps_counters->{$key}->{$_}->{obj}->set(%{$maps_counters->{$key}->{$_}->{set}}); + } + } + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); + + foreach my $key (('global')) { + foreach (keys %{$maps_counters->{$key}}) { + $maps_counters->{$key}->{$_}->{obj}->init(option_results => $self->{option_results}); + } + } + + $self->{statefile_value}->check_options(%options); +} + +sub run { + my ($self, %options) = @_; + $self->{sql} = $options{sql}; + + $self->manage_selection(); + + $self->{new_datas} = {}; + $self->{statefile_value}->read(statefile => 'firebird_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); + $self->{new_datas}->{last_timestamp} = time(); + + my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', ''); + my @exits; + + foreach (sort keys %{$maps_counters->{global}}) { + my $obj = $maps_counters->{global}->{$_}->{obj}; + + $obj->set(instance => 'firebird'); + + my ($value_check) = $obj->execute(values => $self->{firebird}, + new_datas => $self->{new_datas}); + + if ($value_check != 0) { + $long_msg .= $long_msg_append . $obj->output_error(); + $long_msg_append = ', '; + next; + } + my $exit2 = $obj->threshold_check(); + push @exits, $exit2; + + my $output = $obj->output(); + $long_msg .= $long_msg_append . $output; + $long_msg_append = ', '; + + if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) { + $short_msg .= $short_msg_append . $output; + $short_msg_append = ', '; + } + + $obj->perfdata(); + } + + my $exit = $self->{output}->get_most_critical(status => [ @exits ]); + if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { + $self->{output}->output_add(severity => $exit, + short_msg => "Page $short_msg" + ); + } else { + $self->{output}->output_add(short_msg => "Page $long_msg"); + } + + $self->{statefile_value}->write(data => $self->{new_datas}); + $self->{output}->display(); + $self->{output}->exit(); +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{sql}->connect(); + $self->{sql}->query(query => q{SELECT MON$PAGE_READS as PAGE_READS, MON$PAGE_WRITES as PAGE_WRITES, MON$PAGE_FETCHES as PAGE_FETCHES, MON$PAGE_MARKS as PAGE_MARKS FROM MON$IO_STATS mi WHERE mi.MON$STAT_GROUP = 0}); + my $row = $self->{sql}->fetchrow_hashref(); + if (!defined($row)) { + $self->{output}->add_option_msg(short_msg => "Cannot get page informations"); + $self->{output}->option_exit(); + } + + $self->{firebird} = { reads => $row->{PAGE_READS}, writes => $row->{PAGE_WRITES}, + fetches => $row->{PAGE_FETCHES}, marks => $row->{PAGE_MARKS} }; +} + +1; + +__END__ + +=head1 MODE + +Check page statistics on current database. + +=over 8) + +=item B<--warning-*> + +Threshold warning. +Can be: 'reads', 'writes', 'fetches', 'marks'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'reads', 'writes', 'fetches', 'marks'. + +=back + +=cut diff --git a/database/firebird/mode/queries.pm b/database/firebird/mode/queries.pm index 8a1231528..549350b17 100644 --- a/database/firebird/mode/queries.pm +++ b/database/firebird/mode/queries.pm @@ -65,14 +65,11 @@ sub run { $self->{sql}->connect(); $self->{sql}->query(query => q{ - SELECT MON$RECORD_SEQ_READS,MON$RECORD_INSERTS,MON$RECORD_UPDATES,MON$RECORD_DELETES,MON$RECORD_BACKOUTS,MON$RECORD_PURGES,MON$RECORD_EXPUNGES from MON$RECORD_STATS WHERE MON$STAT_GROUP=0 + SELECT MON$RECORD_SEQ_READS,MON$RECORD_INSERTS,MON$RECORD_UPDATES,MON$RECORD_DELETES,MON$RECORD_BACKOUTS,MON$RECORD_PURGES,MON$RECORD_EXPUNGES + FROM MON$RECORD_STATS mr WHERE mr.MON$STAT_GROUP = '0'; }); - my $result = $self->{sql}->fetchall_arrayref(); - if (!($self->{sql}->is_version_minimum(version => '1'))) { - $self->{output}->add_option_msg(short_msg => "Firebird version '" . $self->{sql}->{version} . "' is not supported (need version >= '1')."); - $self->{output}->option_exit(); - } + my $result = $self->{sql}->fetchall_arrayref(); my $new_datas = {}; $self->{statefile_cache}->read(statefile => 'firebird_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); @@ -84,36 +81,37 @@ sub run { $self->{output}->option_exit(); } - my @field = ("seq_reads","inserts","updates","deletes","backouts","purges","expunges"); - my $i=0; + my @field = ("seq_reads", "inserts", "updates", "deletes", "backouts", "purges", "expunges"); + my $i = 0; + my $total_requests = 0; + my $checked = 0; foreach my $name (@field) { - $new_datas->{$name} = $$result[0][$i]; my $old_val = $self->{statefile_cache}->get(name => $name); next if (!defined($old_val) || $$result[0][$i] < $old_val); my $value = int(($$result[0][$i] - $old_val) / ($new_datas->{last_timestamp} - $old_timestamp)); - if ($name ne 'seq_reads') { - $self->{output}->perfdata_add(label => $name . '_requests', + $self->{output}->perfdata_add(label => $name . '_requests', value => $value, min => 0); - $i++; - next; - } - - my $exit_code = $self->{perfdata}->threshold_check(value => $value, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); + $i++; + $total_requests += $value; + $checked = 1; + } + + if ($checked == 1) { + my $exit_code = $self->{perfdata}->threshold_check(value => $total_requests, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("Total requests = %s", $value)); + short_msg => sprintf("Total requests = %s", $total_requests)); $self->{output}->perfdata_add(label => 'total_requests', - value => $value, + value => $total_requests, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); - $i++ } $self->{statefile_cache}->write(data => $new_datas); - if (!defined($old_timestamp)) { + if ($checked == 0) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } @@ -128,7 +126,7 @@ __END__ =head1 MODE -Check average number of queries executed. +Check average number of queries executed on the current database (firebird version >= 2.1) =over 8 diff --git a/database/firebird/mode/slowqueries.pm b/database/firebird/mode/slowqueries.pm deleted file mode 100644 index 0c9e7bcbb..000000000 --- a/database/firebird/mode/slowqueries.pm +++ /dev/null @@ -1,139 +0,0 @@ -# -# Copyright 2015 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::firebird::mode::slowqueries; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::statefile; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.0'; - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - }); - $self->{statefile_cache} = centreon::plugins::statefile->new(%options); - - return $self; -} - -sub check_options { - my ($self, %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(); - } - 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->{statefile_cache}->check_options(%options); -} - -sub run { - my ($self, %options) = @_; - # $options{sql} = sqlmode object - $self->{sql} = $options{sql}; - - $self->{sql}->connect(); - - if (!($self->{sql}->is_version_minimum(version => '1'))) { - $self->{output}->add_option_msg(short_msg => "Firebird version '" . $self->{sql}->{version} . "' is not supported (need version >= '1.x')."); - $self->{output}->option_exit(); - } - - $self->{sql}->query(query => q{SELECT COUNT(*) FROM MON$STATEMENTS INNER JOIN MON$TRANSACTIONS ON (MON$STATEMENTS.MON$ATTACHMENT_ID = MON$TRANSACTIONS.MON$ATTACHMENT_ID)}); - my $result = $self->{sql}->fetchrow_array(); - my $name='slow_query'; - if (!defined($result)) { - $self->{output}->add_option_msg(short_msg => "Cannot get slow queries."); - $self->{output}->option_exit(); - } - - - my $new_datas = {}; - $self->{statefile_cache}->read(statefile => 'firebird_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); - my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); - $new_datas->{last_timestamp} = time(); - - if (defined($old_timestamp) && $new_datas->{last_timestamp} - $old_timestamp == 0) { - $self->{output}->add_option_msg(short_msg => "Need at least one second between two checks."); - $self->{output}->option_exit(); - } - - $new_datas->{$name} = $result; - my $old_val = $self->{statefile_cache}->get(name => $name); - if (defined($old_val) && $result >= $old_val) { - my $value = sprintf("%.2f", ($result - $old_val) / ($new_datas->{last_timestamp} - $old_timestamp)); - - my $exit_code = $self->{perfdata}->threshold_check(value => $value, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("%d slow queries in %d seconds (%.2f/sec)", - ($result - $old_val), ($new_datas->{last_timestamp} - $old_timestamp), $value) - ); - $self->{output}->perfdata_add(label => 'slow_queries_rate', - value => $value, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), - min => 0); - } - - $self->{statefile_cache}->write(data => $new_datas); - if (!defined($old_timestamp)) { - $self->{output}->output_add(severity => 'OK', - short_msg => "Buffer creation..."); - } - - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Check average number of queries detected as "slow" (per seconds). - -=over 8 - -=item B<--warning> - -Threshold warning in queries per seconds. - -=item B<--critical> - -Threshold critical in queries per seconds. - -=back - -=cut diff --git a/database/firebird/mode/users.pm b/database/firebird/mode/users.pm index 3e502f2d9..3b7a3b18b 100644 --- a/database/firebird/mode/users.pm +++ b/database/firebird/mode/users.pm @@ -62,12 +62,7 @@ sub run { $self->{sql}->connect(); - if (!($self->{sql}->is_version_minimum(version => '1'))) { - $self->{output}->add_option_msg(short_msg => "firebird version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.x')."); - $self->{output}->option_exit(); - } - - $self->{sql}->query(query => q{SELECT COUNT(MON$USER) FROM MON$ATTACHMENTS}); + $self->{sql}->query(query => q{SELECT COUNT(MON$USER) FROM MON$ATTACHMENTS WHERE MON$ATTACHMENT_ID <> CURRENT_CONNECTION}); my $result = $self->{sql}->fetchrow_array(); if (!defined($result)) { @@ -80,7 +75,7 @@ sub run { $self->{output}->output_add(severity => $exit_code, short_msg => $msg); - $self->{output}->perfdata_add(label => 'User', value => $result, + $self->{output}->perfdata_add(label => 'users', value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); @@ -95,7 +90,7 @@ __END__ =head1 MODE -Check MySQL uptime. +Check current users connected on the database (firebird version >= 2.1) =over 8 @@ -107,10 +102,6 @@ Threshold warning. Threshold critical. -=item B<--seconds> - -Display uptime in seconds. - =back =cut diff --git a/database/firebird/plugin.pm b/database/firebird/plugin.pm index 3a6f6ac4c..5802402dd 100644 --- a/database/firebird/plugin.pm +++ b/database/firebird/plugin.pm @@ -33,12 +33,13 @@ sub new { $self->{version} = '0.1'; %{$self->{modes}} = ( - 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', - 'memory' => 'database::firebird::mode::memory', - 'users' => 'database::firebird::mode::users', - 'io-stats' => 'database::firebird::mode::iostats', - 'queries' => 'database::firebird::mode::queries', - 'slow-queries' => 'database::firebird::mode::slowqueries', + 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', + 'users' => 'database::firebird::mode::users', + 'pages' => 'database::firebird::mode::pages', + 'memory' => 'database::firebird::mode::memory', + 'queries' => 'database::firebird::mode::queries', + 'long-queries' => 'database::firebird::mode::longqueries', + 'sql' => 'centreon::common::protocols::sql::mode::sql', ); $self->{sql_modes}{firebirdcmd} = 'database::firebird::firebirdcmd'; @@ -84,7 +85,7 @@ __END__ =head1 PLUGIN DESCRIPTION -Check Firebird Server. +Check Firebird Server. It works with version >= 2.1 and sysdba user. =over 8