From b288e7e884ca47683741c3060ac0aa1dfc3e3365 Mon Sep 17 00:00:00 2001
From: qgarnier <qgarnier@centreon.com>
Date: Mon, 10 Jul 2017 13:42:09 +0200
Subject: [PATCH] add oracle mode

---
 .../database/oracle/mode/eventwaitsusage.pm   | 165 +++++++++++++++
 .../oracle/mode/rollbacksegmentusage.pm       | 188 ++++++++++++++++++
 centreon-plugins/database/oracle/plugin.pm    |   2 +
 3 files changed, 355 insertions(+)
 create mode 100644 centreon-plugins/database/oracle/mode/eventwaitsusage.pm
 create mode 100644 centreon-plugins/database/oracle/mode/rollbacksegmentusage.pm

diff --git a/centreon-plugins/database/oracle/mode/eventwaitsusage.pm b/centreon-plugins/database/oracle/mode/eventwaitsusage.pm
new file mode 100644
index 000000000..f116b94a9
--- /dev/null
+++ b/centreon-plugins/database/oracle/mode/eventwaitsusage.pm
@@ -0,0 +1,165 @@
+#
+# Copyright 2017 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::oracle::mode::eventwaitsusage;
+
+use base qw(centreon::plugins::templates::counter);
+
+use strict;
+use warnings;
+use Digest::MD5 qw(md5_hex);
+
+sub set_counters {
+    my ($self, %options) = @_;
+
+    $self->{maps_counters_type} = [
+        { name => 'event', type => 1, cb_prefix_output => 'prefix_event_output', message_multiple => 'All event waits are OK' },
+    ];
+
+    $self->{maps_counters}->{event} = [    
+        { label => 'total-waits-sec', set => {
+                key_values => [ { name => 'total_waits', diff => 1 }, { name => 'display' } ],
+                per_second => 1,
+                output_template => 'Total Waits : %.2f/s',
+                perfdatas => [
+                    { label => 'total_waits', value => 'total_waits_per_second', template => '%.2f',
+                      unit => '/s', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
+                ],
+            }
+        },
+        { label => 'total-waits-time', set => {
+                key_values => [ { name => 'time_waited_micro', diff => 1 }, { name => 'display' } ],
+                closure_custom_calc => $self->can('custom_usage_calc'),
+                output_template => 'Total Waits Time :  %.2f %%', output_use => 'prct_wait', threshold_use => 'prct_wait',
+                perfdatas => [
+                    { label => 'total_waits_time', value => 'prct_wait', template => '%.2f', min => 0, max => 100, unit => '%',
+                      label_extra_instance => 1, instance_use => 'display' },
+                ],
+            }
+        },
+    ];
+}
+
+sub custom_usage_calc {
+    my ($self, %options) = @_;
+
+    $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
+    my $delta_total = $options{new_datas}->{$self->{instance} . '_time_waited_micro'} - $options{old_datas}->{$self->{instance} . '_time_waited_micro'};
+    $self->{result_values}->{prct_wait} = 100 * ($delta_total / 1000000) / $options{delta_time};
+    
+    return 0;
+}
+
+sub new {
+    my ($class, %options) = @_;
+    my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1);
+    bless $self, $class;
+
+    $self->{version} = '1.0';
+    $options{options}->add_options(arguments =>
+                                {
+                                "filter-name:s" => { name => 'filter_name' },
+                                });
+    return $self;
+}
+
+sub prefix_event_output {
+    my ($self, %options) = @_;
+
+    return "Event '" . $options{instance_value}->{display} . "' ";
+}
+
+sub manage_selection {
+    my ($self, %options) = @_;
+    $self->{sql} = $options{sql};
+    $self->{sql}->connect();
+
+    my $query = q{
+        SELECT e.event#, e.name, 
+                NVL(s.total_waits, 0), NVL(s.total_timeouts, 0), NVL(s.time_waited, 0),
+                NVL(s.time_waited_micro, 0), NVL(s.average_wait, 0)
+          FROM v$event_name e LEFT JOIN sys.v_$system_event s ON e.name = s.event
+    };
+    if ($self->{sql}->is_version_minimum(version => '10')) {
+        $query = q{
+            SELECT e.event_id, e.name, 
+                NVL(s.total_waits, 0), NVL(s.total_timeouts, 0), NVL(s.time_waited, 0),
+                NVL(s.time_waited_micro, 0), NVL(s.average_wait, 0)
+            FROM v$event_name e LEFT JOIN sys.v_$system_event s ON e.name = s.event
+        };
+    }
+    
+    $self->{sql}->query(query => $query);
+    my $result = $self->{sql}->fetchall_arrayref();
+
+    $self->{event} = {};
+    foreach my $row (@$result) {
+        my ($name, $total_waits, $time_waited_micro) = ($row->[1], $row->[2], $row->[5]);
+
+        if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
+            $name !~ /$self->{option_results}->{filter_name}/) {
+            $self->{output}->output_add(long_msg => "skipping  '" . $name . "': no matching filter.", debug => 1);
+            next;
+        }
+
+        $self->{event}->{$name} = {
+            display => $name,
+            total_waits => $total_waits,
+            time_waited_micro => $time_waited_micro
+        };
+    }
+    
+    if (scalar(keys %{$self->{event}}) <= 0) {
+        $self->{output}->add_option_msg(short_msg => "No event found.");
+        $self->{output}->option_exit();
+    }
+    
+    $self->{cache_name} = "oracle_" . $options{snmp}->get_hostname()  . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . 
+        (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' .
+        (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all'));
+}
+
+1;
+
+__END__
+
+=head1 MODE
+
+Check Oracle event wait usage.
+
+=over 8
+
+=item B<--warning-*>
+
+Threshold warning.
+Can be: 'total-waits-sec', 'total-waits-time'.
+
+=item B<--critical-*>
+
+Threshold critical.
+Can be: 'total-waits-sec', 'total-waits-time'.
+
+=item B<--filter-name>
+
+Filter by event name. Can be a regex.
+
+=back
+
+=cut
diff --git a/centreon-plugins/database/oracle/mode/rollbacksegmentusage.pm b/centreon-plugins/database/oracle/mode/rollbacksegmentusage.pm
new file mode 100644
index 000000000..fbe3a87d8
--- /dev/null
+++ b/centreon-plugins/database/oracle/mode/rollbacksegmentusage.pm
@@ -0,0 +1,188 @@
+#
+# Copyright 2017 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::oracle::mode::rollbacksegmentusage;
+
+use base qw(centreon::plugins::templates::counter);
+
+use strict;
+use warnings;
+use Digest::MD5 qw(md5_hex);
+
+sub set_counters {
+    my ($self, %options) = @_;
+
+    $self->{maps_counters_type} = [
+        { name => 'segment', type => 0, cb_prefix_output => 'prefix_output' },
+    ];
+
+    $self->{maps_counters}->{segment} = [    
+        { label => 'extends', set => {
+                key_values => [ { name => 'extends', diff => 1 } ],
+                per_second => 1,
+                output_template => 'Extends : %.2f/s',
+                perfdatas => [
+                    { label => 'extends', value => 'extends_per_second', template => '%.2f',
+                      unit => '/s', min => 0 },
+                ],
+            }
+        },
+        { label => 'wraps', set => {
+                key_values => [ { name => 'wraps', diff => 1 } ],
+                per_second => 1,
+                output_template => 'Wraps : %.2f/s',
+                perfdatas => [
+                    { label => 'wraps', value => 'wraps_per_second', template => '%.2f',
+                      unit => '/s', min => 0 },
+                ],
+            }
+        },
+        { label => 'header-contention', set => {
+                key_values => [ { name => 'undoheader', diff => 1 }, { name => 'complete', diff => 1 } ],
+                closure_custom_calc => $self->can('custom_contention_calc'), closure_custom_calc_extra_options => { label_ref => 'header' },
+                output_template => 'Header Contention :  %.2f %%', output_use => 'header_prct', threshold_use => 'header_prct',
+                perfdatas => [
+                    { label => 'header_contention', value => 'header_prct', template => '%.2f', min => 0, max => 100, unit => '%' },
+                ],
+            }
+        },
+        { label => 'block-contention', set => {
+                key_values => [ { name => 'undoblock', diff => 1 }, { name => 'complete', diff => 1 } ],
+                closure_custom_calc => $self->can('custom_contention_calc'), closure_custom_calc_extra_options => { label_ref => 'block' },
+                output_template => 'Block Contention :  %.2f %%', output_use => 'block_prct', threshold_use => 'block_prct',
+                perfdatas => [
+                    { label => 'block_contention', value => 'block_prct', template => '%.2f', min => 0, max => 100, unit => '%' },
+                ],
+            }
+        },
+        { label => 'hit-ratio', set => {
+                key_values => [ { name => 'waits', diff => 1 }, { name => 'gets', diff => 1 } ],
+                closure_custom_calc => $self->can('custom_hitratio_calc'),
+                output_template => 'gets/waits Ratio :  %.2f %%', output_use => 'hit_ratio', threshold_use => 'hit_ratio',
+                perfdatas => [
+                    { label => 'hit_ratio', value => 'hit_ratio', template => '%.2f', min => 0, max => 100, unit => '%' },
+                ],
+            }
+        },
+    ];
+}
+
+sub custom_hitratio_calc {
+    my ($self, %options) = @_;
+
+    my $delta_waits = $options{new_datas}->{$self->{instance} . '_waits'} - $options{old_datas}->{$self->{instance} . '_waits'};
+    my $delta_gets = $options{new_datas}->{$self->{instance} . '_gets'} - $options{old_datas}->{$self->{instance} . '_gets'};
+    $self->{result_values}->{hit_ratio} = 100 - 100 * $self->{delta_waits} / $self->{delta_gets};
+    
+    return 0;
+}
+
+sub custom_contention_calc {
+    my ($self, %options) = @_;
+
+    my $delta_waits = $options{new_datas}->{$self->{instance} . '_complete'} - $options{old_datas}->{$self->{instance} . '_complete'};
+    my $delta_undo = $options{new_datas}->{$self->{instance} . '_undo' . $options{extra_options}->{label_ref}} - $options{old_datas}->{$self->{instance} . '_undo' . $options{extra_options}->{label_ref}};
+    $self->{result_values}->{$options{extra_options}->{label_ref} . '_prct'} = 100 * $delta_undo / $delta_waits;
+    
+    return 0;
+}
+
+sub new {
+    my ($class, %options) = @_;
+    my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1);
+    bless $self, $class;
+
+    $self->{version} = '1.0';
+    $options{options}->add_options(arguments =>
+                                {
+                                });
+    return $self;
+}
+
+sub prefix_output {
+    my ($self, %options) = @_;
+
+    return "Rollback Segment ";
+}
+
+sub manage_selection {
+    my ($self, %options) = @_;
+    $self->{sql} = $options{sql};
+    $self->{sql}->connect();
+
+    my $query = q{
+        SELECT SUM(waits), SUM(gets), SUM(extends), SUM(wraps) FROM v$rollstat
+    };
+    
+    $self->{sql}->query(query => $query);
+    my $result = $self->{sql}->fetchrow_array();
+    $self->{segment} = { waits => $result->[0], gets => $result->[1], extends => $result->[2], wraps => $result->[3] };
+
+    $query = q{
+        SELECT ( 
+          SELECT SUM(count)
+          FROM v$waitstat
+          WHERE class = 'undo header' OR class = 'system undo header'
+        ) undoheader,
+        ( 
+          SELECT SUM(count)
+          FROM v$waitstat
+          WHERE class = 'undo block' OR class = 'system undo block'
+        ) undoblock, 
+        (
+          SELECT SUM(count)
+          FROM v$waitstat
+        ) complete
+        FROM DUAL
+    };
+    $result = $self->{sql}->fetchrow_array();
+    $self->{segment}->{undoheader} = $result->[0];
+    $self->{segment}->{undoblock} = $result->[1];
+    $self->{segment}->{complete} = $result->[2];
+    
+    $self->{cache_name} = "oracle_" . $options{snmp}->get_hostname()  . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . 
+        (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all'));
+}
+
+1;
+
+__END__
+
+=head1 MODE
+
+Check Oracle rollback segment usage.
+
+=over 8
+
+=item B<--warning-*>
+
+Threshold warning.
+Can be: 'header-contention', 'block-contention', 'hit-ratio',
+'extends', 'wraps'.
+
+=item B<--critical-*>
+
+Threshold critical.
+Can be: 'header-contention', 'block-contention', 'hit-ratio',
+'extends', 'wraps'.
+
+=back
+
+=cut
diff --git a/centreon-plugins/database/oracle/plugin.pm b/centreon-plugins/database/oracle/plugin.pm
index a9918646c..8699934f0 100644
--- a/centreon-plugins/database/oracle/plugin.pm
+++ b/centreon-plugins/database/oracle/plugin.pm
@@ -38,10 +38,12 @@ sub new {
                          'corrupted-blocks'         => 'database::oracle::mode::corruptedblocks',
                          'data-files-status'        => 'database::oracle::mode::datafilesstatus',
                          'datacache-hitratio'       => 'database::oracle::mode::datacachehitratio',
+                         'event-waits-usage'        => 'database::oracle::mode::eventwaitsusage',
                          'process-usage'            => 'database::oracle::mode::processusage',
                          'rman-backup-problems'     => 'database::oracle::mode::rmanbackupproblems',
                          'rman-backup-age'          => 'database::oracle::mode::rmanbackupage',
                          'rman-online-backup-age'   => 'database::oracle::mode::rmanonlinebackupage',
+                         'rollback-segment-usage'   => 'database::oracle::mode::rollbacksegmentusage',
                          'tablespace-usage'         => 'database::oracle::mode::tablespaceusage',
                          'session-usage'            => 'database::oracle::mode::sessionusage',
                          'sql'                      => 'centreon::common::protocols::sql::mode::sql',