From edf6b87d19971f23474a65fa9a6869827aa1724a Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 5 Dec 2017 15:57:28 +0100 Subject: [PATCH] enhance redis plugin --- apps/redis/cli/custom/rediscli.pm | 17 +-- apps/redis/cli/mode/clients.pm | 14 +- apps/redis/cli/mode/cluster.pm | 128 ---------------- apps/redis/cli/mode/commands.pm | 17 ++- apps/redis/cli/mode/connections.pm | 26 ++-- apps/redis/cli/mode/cpu.pm | 13 +- apps/redis/cli/mode/memory.pm | 55 +++---- apps/redis/cli/mode/persistence.pm | 201 ++++++++++++------------- apps/redis/cli/mode/replication.pm | 227 ++++++++++++++--------------- apps/redis/cli/plugin.pm | 1 - 10 files changed, 273 insertions(+), 426 deletions(-) delete mode 100644 apps/redis/cli/mode/cluster.pm diff --git a/apps/redis/cli/custom/rediscli.pm b/apps/redis/cli/custom/rediscli.pm index f17c2d96e..5b95f8e02 100644 --- a/apps/redis/cli/custom/rediscli.pm +++ b/apps/redis/cli/custom/rediscli.pm @@ -54,20 +54,15 @@ sub new { return $self; } -# Method to manage multiples sub set_options { my ($self, %options) = @_; - # options{options_result} $self->{option_results} = $options{option_results}; } -# Method to manage multiples sub set_defaults { my ($self, %options) = @_; - # options{default} - - # Manage default value + foreach (keys %{$options{default}}) { if ($_ eq $self->{mode}) { for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) { @@ -99,15 +94,19 @@ sub check_options { return 0; } +sub get_connection_info { + my ($self, %options) = @_; + + return $self->{hostname} . ":" . $self->{port}; +} + sub get_info { my ($self, %options) = @_; - $self->{redis} = Redis->new(server => $self->{hostname}.":".$self->{port}); + $self->{redis} = Redis->new(server => $self->{hostname} . ":" . $self->{port}); my $response = $self->{redis}->info; - my $items; - foreach my $attributes (keys %{$response}) { $items->{$attributes} = $response->{$attributes}; } diff --git a/apps/redis/cli/mode/clients.pm b/apps/redis/cli/mode/clients.pm index 547e0e409..21a4cd312 100644 --- a/apps/redis/cli/mode/clients.pm +++ b/apps/redis/cli/mode/clients.pm @@ -85,13 +85,13 @@ sub new { sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - $self->{global} = { 'connected_clients' => $self->{results}->{connected_clients}, - 'blocked_clients' => $self->{results}->{blocked_clients}, - 'client_longest_output_list' => $self->{results}->{client_longest_output_list}, - 'client_biggest_input_buf' => $self->{results}->{client_biggest_input_buf}}; + my $results = $options{custom}->get_info(); + $self->{global} = { + connected_clients => $results->{connected_clients}, + blocked_clients => $results->{blocked_clients}, + client_longest_output_list => $results->{client_longest_output_list}, + client_biggest_input_buf => $results->{client_biggest_input_buf}, + }; } 1; diff --git a/apps/redis/cli/mode/cluster.pm b/apps/redis/cli/mode/cluster.pm deleted file mode 100644 index 0c0f613dc..000000000 --- a/apps/redis/cli/mode/cluster.pm +++ /dev/null @@ -1,128 +0,0 @@ -# -# 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 apps::redis::cli::mode::cluster; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; - -my $thresholds = { - global => [ - ['disabled', 'CRITICAL'], - ['enabled', 'OK'], - ], -}; - -my %map_status = ( - 0 => 'disabled', - 1 => 'enabled', -); - -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 => - { - "threshold-overload:s@" => { name => 'threshold_overload' }, - }); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ('global', $1, $2); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } -} - - -sub get_severity { - my ($self, %options) = @_; - my $status = 'UNKNOWN'; # default - - if (defined($self->{overload_th}->{$options{section}})) { - foreach (@{$self->{overload_th}->{$options{section}}}) { - if ($options{value} =~ /$_->{filter}/i) { - $status = $_->{status}; - return $status; - } - } - } - foreach (@{$thresholds->{$options{section}}}) { - if ($options{value} =~ /$$_[0]/i) { - $status = $$_[1]; - return $status; - } - } - - return $status; -} - -sub run { - my ($self, %options) = @_; - - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - my $exit = $self->get_severity(section => 'global', value => $map_status{$items->{cluster_enabled}}); - - $self->{output}->output_add(severity => $exit, short_msg => sprintf("Cluster is '%s'", $map_status{$items->{cluster_enabled}})); - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Check cluster status - -=over 8 - -=item B<--threshold-overload> - -Set to overload default threshold values (syntax: status,regexp) -Example: --threshold-overload='CRITICAL,disabled' - -=back - -=cut diff --git a/apps/redis/cli/mode/commands.pm b/apps/redis/cli/mode/commands.pm index f648019cc..0ceeab764 100644 --- a/apps/redis/cli/mode/commands.pm +++ b/apps/redis/cli/mode/commands.pm @@ -21,16 +21,16 @@ package apps::redis::cli::mode::commands; use base qw(centreon::plugins::templates::counter); -use Digest::MD5 qw(md5_hex); use strict; use warnings; +use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'global', type => 0, cb_prefix_output => 'prefix_output' } + { name => 'global', type => 0, cb_prefix_output => 'prefix_output' }, ]; $self->{maps_counters}->{global} = [ @@ -76,13 +76,14 @@ sub new { sub manage_selection { my ($self, %options) = @_; - $self->{cache_name} = "redis_" . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . md5_hex('all'); + $self->{cache_name} = "redis_" . $self->{mode} . '_' . $options{custom}->get_connection_info() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - $self->{global} = { 'total_commands_processed' => $self->{results}->{total_commands_processed}, - 'instantaneous_ops_per_sec' => $self->{results}->{instantaneous_ops_per_sec}}; + my $results = $options{custom}->get_info(); + $self->{global} = { + total_commands_processed => $results->{total_commands_processed}, + instantaneous_ops_per_sec => $results->{instantaneous_ops_per_sec}, + }; } 1; diff --git a/apps/redis/cli/mode/connections.pm b/apps/redis/cli/mode/connections.pm index e834f0a05..40032ba64 100644 --- a/apps/redis/cli/mode/connections.pm +++ b/apps/redis/cli/mode/connections.pm @@ -21,17 +21,17 @@ package apps::redis::cli::mode::connections; use base qw(centreon::plugins::templates::counter); -use Digest::MD5 qw(md5_hex); use strict; use warnings; +use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'connections', type => 0, cb_prefix_output => 'prefix_connections_output' }, - { name => 'traffic', type => 0, cb_prefix_output => 'prefix_traffic_output' } + { name => 'traffic', type => 0, cb_prefix_output => 'prefix_traffic_output' }, ]; $self->{maps_counters}->{connections} = [ @@ -59,7 +59,7 @@ sub set_counters { output_template => 'Traffic In: %s %s/s', per_second => 1, output_change_bytes => 2, perfdatas => [ - { label => 'traffic_in', value => 'total_net_input_bytes_per_second', template => '%s', min => 0, unit => 'b/s' }, + { label => 'traffic_in', value => 'total_net_input_bytes_per_second', template => '%d', min => 0, unit => 'b/s' }, ], }, }, @@ -68,7 +68,7 @@ sub set_counters { output_template => 'Traffic Out: %s %s/s', per_second => 1, output_change_bytes => 2, perfdatas => [ - { label => 'traffic_out', value => 'total_net_output_bytes_per_second', template => '%s', min => 0, unit => 'b/s' }, + { label => 'traffic_out', value => 'total_net_output_bytes_per_second', template => '%d', min => 0, unit => 'b/s' }, ], }, }, @@ -104,16 +104,20 @@ sub new { sub manage_selection { my ($self, %options) = @_; - $self->{cache_name} = "redis_" . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . md5_hex('all'); + $self->{cache_name} = "redis_" . $self->{mode} . '_' . $options{custom}->get_connection_info() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); + my $results = $options{custom}->get_info(); - $self->{connections} = { 'total_connections_received' => $self->{results}->{total_connections_received}, - 'rejected_connections' => $self->{results}->{rejected_connections}}; + $self->{connections} = { + total_connections_received => $results->{total_connections_received}, + rejected_connections => $results->{rejected_connections}, + }; - $self->{traffic} = { 'total_net_input_bytes' => $self->{results}->{total_net_input_bytes}, - 'total_net_output_bytes' => $self->{results}->{total_net_output_bytes}}; + $self->{traffic} = { + total_net_input_bytes => $results->{total_net_input_bytes} * 8, + total_net_output_bytes => $results->{total_net_output_bytes} * 8, + }; } 1; diff --git a/apps/redis/cli/mode/cpu.pm b/apps/redis/cli/mode/cpu.pm index 7a483185a..84012de27 100644 --- a/apps/redis/cli/mode/cpu.pm +++ b/apps/redis/cli/mode/cpu.pm @@ -91,13 +91,14 @@ sub new { sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); + my $results = $options{custom}->get_info(); - $self->{global} = { 'used_cpu_sys' => $self->{results}->{used_cpu_sys}, - 'used_cpu_user' => $self->{results}->{used_cpu_user}, - 'used_cpu_sys_children' => $self->{results}->{used_cpu_sys_children}, - 'used_cpu_user_children' => $self->{results}->{used_cpu_user_children}}; + $self->{global} = { + used_cpu_sys => $results->{used_cpu_sys}, + used_cpu_user => $results->{used_cpu_user}, + used_cpu_sys_children => $results->{used_cpu_sys_children}, + used_cpu_user_children => $results->{used_cpu_user_children}, + }; } 1; diff --git a/apps/redis/cli/mode/memory.pm b/apps/redis/cli/mode/memory.pm index 5f2c69fa1..6aef79436 100644 --- a/apps/redis/cli/mode/memory.pm +++ b/apps/redis/cli/mode/memory.pm @@ -25,6 +25,8 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; +my $instance_mode; + sub custom_usage_perfdata { my ($self, %options) = @_; @@ -35,8 +37,6 @@ sub custom_usage_perfdata { min => 0, max => $self->{result_values}->{total}); } -my $instance_mode; - sub custom_usage_threshold { my ($self, %options) = @_; @@ -80,13 +80,13 @@ sub set_counters { $self->{maps_counters_type} = [ { name => 'used', type => 0 }, - { name => 'rss', type => 0 }, - { name => 'peak', type => 0 }, - { name => 'overhead', type => 0 }, - { name => 'startup', type => 0 }, - { name => 'dataset', type => 0 }, - { name => 'lua', type => 0 }, - { name => 'stats', type => 0, cb_prefix_output => 'prefix_stats_output' } + { name => 'rss', type => 0, skipped_code => { -10 => 1 } }, + { name => 'peak', type => 0, skipped_code => { -10 => 1 } }, + { name => 'overhead', type => 0, skipped_code => { -10 => 1 } }, + { name => 'startup', type => 0, skipped_code => { -10 => 1 } }, + { name => 'dataset', type => 0, skipped_code => { -10 => 1 } }, + { name => 'lua', type => 0, skipped_code => { -10 => 1 } }, + { name => 'stats', type => 0, cb_prefix_output => 'prefix_stats_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{used} = [ @@ -225,31 +225,32 @@ sub check_options { } my $metrics = { - 'used_memory' => { label => 'used', display => 'Used' }, - 'used_memory_rss' => { label => 'rss', display => 'Rss' }, - 'used_memory_peak' => { label => 'peak', display => 'Peak' }, - 'used_memory_overhead' => { label => 'overhead', display => 'Overhead' }, - 'used_memory_startup' => { label => 'startup', display => 'Startup' }, - 'used_memory_dataset' => { label => 'dataset', display => 'Dataset' }, - 'used_memory_lua' => { label => 'lua', display => 'Lua' }, + used_memory => { label => 'used', display => 'Used' }, + used_memory_rss => { label => 'rss', display => 'Rss' }, + used_memory_peak => { label => 'peak', display => 'Peak' }, + used_memory_overhead => { label => 'overhead', display => 'Overhead' }, + used_memory_startup => { label => 'startup', display => 'Startup' }, + used_memory_dataset => { label => 'dataset', display => 'Dataset' }, + used_memory_lua => { label => 'lua', display => 'Lua' }, }; sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - foreach my $type (keys $metrics) { - $self->{$metrics->{$type}->{label}} = { 'display' => $metrics->{$type}->{display}, - 'label' => $metrics->{$type}->{label}, - 'used' => $self->{results}->{$type}, - 'total' => $self->{results}->{total_system_memory} }; + my $results = $options{custom}->get_info(); + foreach my $type (keys %$metrics) { + next if (!defined($results->{$type})); + $self->{$metrics->{$type}->{label}} = { display => $metrics->{$type}->{display}, + label => $metrics->{$type}->{label}, + used => $results->{$type}, + total => $results->{total_system_memory} }; } - $self->{stats} = { 'mem_fragmentation_ratio' => $self->{results}->{mem_fragmentation_ratio}, - 'active_defrag_running' => $self->{results}->{active_defrag_running}, - 'lazyfree_pending_objects' => $self->{results}->{lazyfree_pending_objects} }; + $self->{stats} = { + mem_fragmentation_ratio => $results->{mem_fragmentation_ratio}, + active_defrag_running => $results->{active_defrag_running}, + lazyfree_pending_objects => $results->{lazyfree_pending_objects}, + }; } 1; diff --git a/apps/redis/cli/mode/persistence.pm b/apps/redis/cli/mode/persistence.pm index 07bc62988..db141d38c 100644 --- a/apps/redis/cli/mode/persistence.pm +++ b/apps/redis/cli/mode/persistence.pm @@ -25,30 +25,24 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; -my $thresholds = { - status => [ - ['fail', 'CRITICAL'], - ['ok', 'OK'], - ], - progress => [ - ['stopped', 'WARNING'], - ['in progress', 'OK'], - ], -}; - -my %map_status = ( - 0 => 'stopped', - 1 => 'in progress', -); +my $instance_mode; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'global', type => 0 } + { name => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'status' }, { name => 'progress_status' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, { label => 'changes', set => { key_values => [ { name => 'rdb_changes_since_last_save' } ], output_template => 'Number of changes since the last dump: %s', @@ -93,6 +87,45 @@ sub set_counters { ]; } +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = sprintf("RDB save status is '%s' [progress status: %s]", $self->{result_values}->{status}, $self->{result_values}->{progress_status}); + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{progress_status} = $options{new_datas}->{$self->{instance} . '_progress_status'}; + return 0; +} + sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); @@ -102,7 +135,8 @@ sub new { $options{options}->add_options(arguments => { - "threshold-overload:s@" => { name => 'threshold_overload' }, + "warning-status:s" => { name => 'warning_status', default => '%{sync_status} =~ /in progress/i' }, + "critical-status:s" => { name => 'critical_status', default => '%{link_status} =~ /down/i' }, }); return $self; @@ -110,70 +144,41 @@ sub new { sub check_options { my ($self, %options) = @_; - $self->SUPER::init(%options); - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ($1, $2, $3); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); } - -sub get_severity { +sub change_macros { my ($self, %options) = @_; - my $status = 'UNKNOWN'; # default - - if (defined($self->{overload_th}->{$options{section}})) { - foreach (@{$self->{overload_th}->{$options{section}}}) { - if ($options{value} =~ /$_->{filter}/i) { - $status = $_->{status}; - return $status; - } + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; } } - foreach (@{$thresholds->{$options{section}}}) { - if ($options{value} =~ /$$_[0]/i) { - $status = $$_[1]; - return $status; - } - } - - return $status; } +my %map_status = ( + 0 => 'stopped', + 1 => 'in progress', +); + sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - my @exits; - - push @exits, $self->get_severity(section => 'status', value => $self->{results}->{rdb_last_bgsave_status}); - push @exits, $self->get_severity(section => 'progess', value => $map_status{$self->{results}->{rdb_bgsave_in_progress}}); - - $self->{output}->output_add(short_msg => sprintf("RDB save is in '%s' status", $self->{results}->{rdb_last_bgsave_status})); - $self->{output}->output_add(short_msg => sprintf("RDB save is '%s'", $map_status{$self->{results}->{rdb_bgsave_in_progress}})); - - $self->{global} = { 'rdb_changes_since_last_save' => $self->{results}->{rdb_changes_since_last_save}, - 'rdb_last_save_time' => centreon::plugins::misc::change_seconds(value => time() - $self->{results}->{rdb_last_save_time}), - 'rdb_last_save_time_sec' => time() - $self->{results}->{rdb_last_save_time}, - 'rdb_last_cow_size' => $self->{results}->{rdb_last_cow_size}, - 'rdb_last_bgsave_time' => $self->{results}->{rdb_last_bgsave_time_sec}, - 'rdb_current_bgsave_time' => $self->{results}->{rdb_current_bgsave_time_sec}}; - - my $exit = $self->{output}->get_most_critical(status => \@exits); - $self->{output}->output_add(severity => $exit); + my $results = $options{custom}->get_info(); + $self->{global} = { + status => $results->{rdb_last_bgsave_status}, + progress_status => $map_status{$results->{rdb_bgsave_in_progress}}, + rdb_changes_since_last_save => $results->{rdb_changes_since_last_save}, + rdb_last_save_time => centreon::plugins::misc::change_seconds(value => time() - $results->{rdb_last_save_time}), + rdb_last_save_time_sec => time() - $results->{rdb_last_save_time}, + rdb_last_cow_size => $results->{rdb_last_cow_size}, + rdb_last_bgsave_time => $results->{rdb_last_bgsave_time_sec}, + rdb_current_bgsave_time => $results->{rdb_current_bgsave_time_sec} + }; } 1; @@ -182,55 +187,31 @@ __END__ =head1 MODE -Check RDB persistence status +Check RDB persistence status. =over 8 -=item B<--threshold-overload> +=item B<--warning-status> -Set to overload default threshold values (syntax: section,status,regexp) -Example: --threshold-overload='status,CRITICAL,ok' -Section can be: 'status', 'progress' +Set warning threshold for status (Default: '%{progress_status} =~ /in progress/i'). +Can used special variables like: %{progress_status}, %{status} -=item B<--warning-changes> +=item B<--critical-status> -Warning threshold for number of changes since the last dump +Set critical threshold for status (Default: '%{status} =~ /fail/i'). +Can used special variables like: %{progress_status}, %{status} -=item B<--critical-changes> +=item B<--warning-*> -Critical threshold for number of changes since the last dump +Threshold warning. +Can be: 'changes', 'last-save', 'save-size', +'last-save-duration', 'current-save-duration'. -=item B<--warning-last-save> +=item B<--critical-*> -Warning threshold for time since last successful save (in second) - -=item B<--critical-last-save> - -Critical threshold for time since last successful save (in second) - -=item B<--warning-save-size> - -Warning threshold for size of last save (in bytes) - -=item B<--critical-save-size> - -Critical threshold for size of last save (in bytes) - -=item B<--warning-last-save-duration> - -Warning threshold for duration of last save (in second) - -=item B<--critical-last-save-duration> - -Critical threshold for duration of last save (in second) - -=item B<--warning-current-save-duration> - -Warning threshold for current of last save (in second) - -=item B<--critical-current-save-duration> - -Critical threshold for current of last save (in second) +Threshold critical. +Can be: 'changes', 'last-save', 'save-size', +'last-save-duration', 'current-save-duration'. =back diff --git a/apps/redis/cli/mode/replication.pm b/apps/redis/cli/mode/replication.pm index 1004d545f..515d80518 100644 --- a/apps/redis/cli/mode/replication.pm +++ b/apps/redis/cli/mode/replication.pm @@ -25,32 +25,26 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; -my $thresholds = { - link => [ - ['down', 'CRITICAL'], - ['up', 'OK'], - ], - sync => [ - ['stopped', 'OK'], - ['in progress', 'WARNING'], - ], -}; - -my %map_sync = ( - 0 => 'stopped', - 1 => 'in progress', -); +my $instance_mode; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'global', type => 0 }, - { name => 'master', type => 0 }, - { name => 'slave', type => 0 } + { name => 'global', type => 0, skipped_code => { -10 => 1 } }, + { name => 'master', type => 0, skipped_code => { -10 => 1 } }, + { name => 'slave', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'link_status' }, { name => 'sync_status' }, { name => 'role' }, { name => 'cluster_state' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, { label => 'connected-slaves', set => { key_values => [ { name => 'connected_slaves' } ], output_template => 'Number of connected slaves: %s', @@ -108,6 +102,51 @@ sub set_counters { ]; } +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = sprintf("Node role is '%s' [cluster: %s]", $self->{result_values}->{role}, $self->{result_values}->{cluster_state}); + if ($self->{result_values}->{role} eq 'slave') { + $msg .= sprintf(" [link status: %s] [sync status: %s]", + $self->{result_values}->{link_status}, $self->{result_values}->{sync_status}); + } + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{role} = $options{new_datas}->{$self->{instance} . '_role'}; + $self->{result_values}->{sync_status} = $options{new_datas}->{$self->{instance} . '_sync_status'}; + $self->{result_values}->{link_status} = $options{new_datas}->{$self->{instance} . '_link_status'}; + $self->{result_values}->{cluster_state} = $options{new_datas}->{$self->{instance} . '_cluster_state'}; + return 0; +} + sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); @@ -117,7 +156,8 @@ sub new { $options{options}->add_options(arguments => { - "threshold-overload:s@" => { name => 'threshold_overload' }, + "warning-status:s" => { name => 'warning_status', default => '%{sync_status} =~ /in progress/i' }, + "critical-status:s" => { name => 'critical_status', default => '%{link_status} =~ /down/i' }, }); return $self; @@ -125,79 +165,52 @@ sub new { sub check_options { my ($self, %options) = @_; - $self->SUPER::init(%options); - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ($1, $2, $3); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); } - -sub get_severity { +sub change_macros { my ($self, %options) = @_; - my $status = 'UNKNOWN'; # default - - if (defined($self->{overload_th}->{$options{section}})) { - foreach (@{$self->{overload_th}->{$options{section}}}) { - if ($options{value} =~ /$_->{filter}/i) { - $status = $_->{status}; - return $status; - } + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; } } - foreach (@{$thresholds->{$options{section}}}) { - if ($options{value} =~ /$$_[0]/i) { - $status = $$_[1]; - return $status; - } - } - - return $status; } +my %map_sync = ( + 0 => 'stopped', + 1 => 'in progress', +); + +my %map_cluster_state = ( + 0 => 'disabled', + 1 => 'enabled', +); + sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - my @exits; + my $results = $options{custom}->get_info(); - $self->{output}->output_add(short_msg => sprintf("Node is '%s'", $self->{results}->{role})); + $self->{global} = { + connected_slaves => $results->{connected_slaves}, + role => $results->{role}, + cluster_state => defined($results->{cluster_enabled}) ? $map_cluster_state{$results->{cluster_enabled}} : '-', + link_status => defined($results->{master_link_status}) ? $results->{master_link_status} : '-', + sync_status => defined($results->{master_sync_in_progress}) ? $map_sync{$results->{master_sync_in_progress}} : '-', + }; - $self->{global} = { 'connected_slaves' => $self->{results}->{connected_slaves} }; - - if ($self->{results}->{role} =~ /master/) { - $self->{master} = { 'master_repl_offset' => $self->{results}->{master_repl_offset} }; - } elsif ($self->{results}->{role} =~ /slave/) { - $self->{output}->output_add(short_msg => sprintf("Link with master '%s:%s' is '%s', Sync is '%s'", - $self->{results}->{master_host}, - $self->{results}->{master_port}, - $self->{results}->{master_link_status}, - $map_sync{$self->{results}->{master_sync_in_progress}})); - - push @exits, $self->get_severity(section => 'link', value => $self->{results}->{master_link_status}); - push @exits, $self->get_severity(section => 'sync', value => $map_sync{$self->{results}->{master_sync_in_progress}}); - - $self->{slave} = { 'master_last_io_seconds_ago' => $self->{results}->{master_last_io_seconds_ago}, - 'slave_repl_offset' => $self->{results}->{slave_repl_offset}, - 'slave_priority' => $self->{results}->{slave_priority}, - 'slave_read_only' => $self->{results}->{slave_read_only} }; - } - - my $exit = $self->{output}->get_most_critical(status => \@exits); - $self->{output}->output_add(severity => $exit); + $self->{master} = { master_repl_offset => $results->{master_repl_offset} }; + $self->{slave} = { + master_last_io_seconds_ago => $results->{master_last_io_seconds_ago}, + slave_repl_offset => $results->{slave_repl_offset}, + slave_priority => $results->{slave_priority}, + slave_read_only => $results->{slave_read_only}, + }; } 1; @@ -206,55 +219,31 @@ __END__ =head1 MODE -Check replication status +Check replication status. =over 8 -=item B<--threshold-overload> +=item B<--warning-status> -Set to overload default threshold values (syntax: section,status,regexp) -Example: --threshold-overload='link,OK,down' -Section can be: 'link', 'sync' +Set warning threshold for status (Default: '%{sync_status} =~ /in progress/i'). +Can used special variables like: %{sync_status}, %{link_status}, %{cluster_state} -=item B<--warning-connected-slaves> +=item B<--critical-status> -Warning threshold for number of connected slave +Set critical threshold for status (Default: '%{link_status} =~ /down/i'). +Can used special variables like: %{sync_status}, %{link_status}, %{cluster_state} -=item B<--critical-connected-slaves> +=item B<--warning-*> -Critical threshold for number of connected slave +Threshold warning. +Can be: 'connected-slaves', 'master-repl-offset', +'master-last-io', 'slave-priority', 'slave-read-only'. -=item B<--warning-master-repl-offset> +=item B<--critical-*> -Warning threshold for master replication offset (in second) - -=item B<--critical-master-repl-offset> - -Critical threshold for master replication offset (in second) - -=item B<--warning-master-last-io> - -Warning threshold for last interaction with master (in second) - -=item B<--critical-master-last-io> - -Critical threshold for last interaction with master (in second) - -=item B<--warning-slave-priority> - -Warning threshold for slave priority - -=item B<--critical-slave-priority> - -Critical threshold for slave priority - -=item B<--warning-slave-read-only> - -Warning threshold for slave being in read-only - -=item B<--critical-slave-read-only> - -Critical threshold for slave being in read-only +Threshold critical. +Can be: 'connected-slaves', 'master-repl-offset', +'master-last-io', 'slave-priority', 'slave-read-only'. =back diff --git a/apps/redis/cli/plugin.pm b/apps/redis/cli/plugin.pm index 2496285c5..a11ad34e1 100644 --- a/apps/redis/cli/plugin.pm +++ b/apps/redis/cli/plugin.pm @@ -32,7 +32,6 @@ sub new { $self->{version} = '1.0'; %{$self->{modes}} = ( 'clients' => 'apps::redis::cli::mode::clients', - 'cluster' => 'apps::redis::cli::mode::cluster', 'commands' => 'apps::redis::cli::mode::commands', 'connections' => 'apps::redis::cli::mode::connections', 'cpu' => 'apps::redis::cli::mode::cpu',