diff --git a/apps/elasticsearch/restapi/mode/cluster.pm b/apps/elasticsearch/restapi/mode/cluster.pm deleted file mode 100644 index ba0ac0c11..000000000 --- a/apps/elasticsearch/restapi/mode/cluster.pm +++ /dev/null @@ -1,167 +0,0 @@ -# -# Copyright 2019 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::elasticsearch::restapi::mode::cluster; - -use base qw(centreon::plugins::templates::counter); - -use strict; -use warnings; -use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); - -sub custom_status_output { - my ($self, %options) = @_; - my $msg = "Cluster '" . $self->{result_values}->{display} . "' Status : " . $self->{result_values}->{status}; - - return $msg; -} - -sub custom_status_calc { - my ($self, %options) = @_; - - $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; - $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; - return 0; -} - -sub set_counters { - my ($self, %options) = @_; - - $self->{maps_counters_type} = [ - { name => 'global', type => 0 }, - ]; - - $self->{maps_counters}->{global} = [ - { label => 'status', threshold => 0, set => { - key_values => [ { name => 'status' }, { name => 'display' } ], - 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 => \&catalog_status_threshold, - } - }, - { label => 'active-primary-shards', set => { - key_values => [ { name => 'active_primary_shards' } ], - output_template => 'Active Primary Shards : %s', - perfdatas => [ - { label => 'active_primary_shards', value => 'active_primary_shards_absolute', template => '%s', - min => 0 }, - ], - } - }, - { label => 'active-shards', set => { - key_values => [ { name => 'active_shards' } ], - output_template => 'Active Shards : %s', - perfdatas => [ - { label => 'active_shards', value => 'active_shards_absolute', template => '%s', - min => 0 }, - ], - } - }, - { label => 'unassigned-shards', set => { - key_values => [ { name => 'unassigned_shards' } ], - output_template => 'Unassigned Shards : %s', - perfdatas => [ - { label => 'unassigned_shards', value => 'unassigned_shards_absolute', template => '%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 => - { - "elastic-path:s" => { name => 'elastic_path', default => '/_cluster/health' }, - "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /yellow/i' }, - "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /red/i' }, - }); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::check_options(%options); - - $self->change_macros(macros => ['warning_status', 'critical_status']); -} - -sub manage_selection { - my ($self, %options) = @_; - - my $result = $options{custom}->get(path => $self->{option_results}->{elastic_path}); - $self->{global} = { - display => $result->{cluster_name}, - status => $result->{status}, - active_primary_shards => $result->{active_primary_shards}, - active_shards => $result->{active_shards}, - unassigned_shards => $result->{unassigned_shards}, - }; -} - -1; - -__END__ - -=head1 MODE - -Check Elasticsearch cluster. - -=over 8 - -=item B<--elastic-path> - -Set path to get Elasticsearch information (Default: '/_cluster/health') - -=item B<--filter-counters> - -Only display some counters (regexp can be used). -Example: --filter-counters='^status$' - -=item B<--warning-*> - -Threshold warning. -Can be: 'active-primary-shards', 'active-shards', 'unassigned-shards'. - -=item B<--critical-*> - -Threshold critical. -Can be: 'active-primary-shards', 'active-shards', 'unassigned-shards'. - -=item B<--warning-status> - -Set warning threshold for status (Default: '%{status} =~ /yellow/i') -Can used special variables like: %{status}. - -=item B<--critical-status> - -Set critical threshold for status (Default: '%{status} =~ /red/i'). -Can used special variables like: %{status}. - -=back - -=cut diff --git a/apps/elasticsearch/restapi/mode/nodes.pm b/apps/elasticsearch/restapi/mode/nodes.pm deleted file mode 100644 index 4e3ff668f..000000000 --- a/apps/elasticsearch/restapi/mode/nodes.pm +++ /dev/null @@ -1,144 +0,0 @@ -# -# Copyright 2019 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::elasticsearch::restapi::mode::nodes; - -use base qw(centreon::plugins::templates::counter); - -use strict; -use warnings; - -sub set_counters { - my ($self, %options) = @_; - - $self->{maps_counters_type} = [ - { name => 'nodes', type => 0, cb_prefix_output => 'prefix_output' }, - ]; - - $self->{maps_counters}->{nodes} = [ - { label => 'total', set => { - key_values => [ { name => 'total' } ], - output_template => 'Total : %s', - perfdatas => [ - { label => 'total', value => 'total_absolute', template => '%s', - min => 0 }, - ], - } - }, - { label => 'masteronly', set => { - key_values => [ { name => 'master_only' } ], - output_template => 'Master Only : %s', - perfdatas => [ - { label => 'master_only', value => 'master_only_absolute', template => '%s', - min => 0 }, - ], - } - }, - { label => 'dataonly', set => { - key_values => [ { name => 'data_only' } ], - output_template => 'Data Only : %s', - perfdatas => [ - { label => 'data_only', value => 'data_only_absolute', template => '%s', - min => 0 }, - ], - } - }, - { label => 'masterdata', set => { - key_values => [ { name => 'master_data' } ], - output_template => 'Master Data : %s', - perfdatas => [ - { label => 'master_data', value => 'master_data_absolute', template => '%s', - min => 0 }, - ], - } - }, - { label => 'client', set => { - key_values => [ { name => 'client' } ], - output_template => 'Client : %s', - perfdatas => [ - { label => 'client', value => 'client_absolute', template => '%s', - min => 0 }, - ], - } - }, - ]; -} - -sub prefix_output { - my ($self, %options) = @_; - - return "Nodes "; -} - -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 => - { - "elastic-path:s" => { name => 'elastic_path', default => '/_cluster/stats' }, - }); - - return $self; -} - -sub manage_selection { - my ($self, %options) = @_; - - my $result = $options{custom}->get(path => $self->{option_results}->{elastic_path}); - $self->{nodes} = { - %{$result->{nodes}->{count}} - }; -} - -1; - -__END__ - -=head1 MODE - -Check Elasticsearch nodes. - -=over 8 - -=item B<--elastic-path> - -Set path to get Elasticsearch information (Default: '/_cluster/stats') - -=item B<--filter-counters> - -Only display some counters (regexp can be used). -Example: --filter-counters='^total$' - -=item B<--warning-*> - -Threshold warning. -Can be: 'total', 'masteronly', 'dataonly', 'masterdata', 'client'. - -=item B<--critical-*> - -Threshold critical. -Can be: 'total', 'masteronly', 'dataonly', 'masterdata', 'client'. - -=back - -=cut diff --git a/apps/elasticsearch/restapi/custom/api.pm b/database/elasticsearch/restapi/custom/api.pm similarity index 97% rename from apps/elasticsearch/restapi/custom/api.pm rename to database/elasticsearch/restapi/custom/api.pm index 389f6b76b..96532c46a 100644 --- a/apps/elasticsearch/restapi/custom/api.pm +++ b/database/elasticsearch/restapi/custom/api.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package apps::elasticsearch::restapi::custom::api; +package database::elasticsearch::restapi::custom::api; use strict; use warnings; @@ -128,8 +128,8 @@ sub get { $self->settings(); - my $response = $self->{http}->request(url_path => $options{path}, - critical_status => '', warning_status => ''); + my $response = $self->{http}->request(url_path => $options{path}, critical_status => '', warning_status => ''); + my $content; eval { $content = JSON::XS->new->utf8->decode($response); diff --git a/database/elasticsearch/restapi/mode/clusterstatistics.pm b/database/elasticsearch/restapi/mode/clusterstatistics.pm new file mode 100644 index 000000000..eb15ed556 --- /dev/null +++ b/database/elasticsearch/restapi/mode/clusterstatistics.pm @@ -0,0 +1,292 @@ +# +# Copyright 2019 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::elasticsearch::restapi::mode::clusterstatistics; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); + +sub custom_status_output { + my ($self, %options) = @_; + my $msg = "Cluster '" . $self->{result_values}->{display} . "' Status '" . $self->{result_values}->{status} . "'"; + + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'status' }, { name => 'display' } ], + 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 => \&catalog_status_threshold, + } + }, + { label => 'nodes-total', nlabel => 'nodes.total.count', set => { + key_values => [ { name => 'nodes_total' } ], + output_template => 'Nodes: %d', + perfdatas => [ + { value => 'nodes_total_absolute', template => '%d', + min => 0 }, + ], + } + }, + { label => 'nodes-data', nlabel => 'nodes.data.count', display_ok => 0, set => { + key_values => [ { name => 'nodes_data' }, { name => 'nodes_total' } ], + output_template => 'Nodes Data: %d', + perfdatas => [ + { value => 'nodes_data_absolute', template => '%d', + min => 0, max => 'nodes_total_absolute' }, + ], + } + }, + { label => 'nodes-coordinating', nlabel => 'nodes.coordinating.count', display_ok => 0, set => { + key_values => [ { name => 'nodes_coordinating' }, { name => 'nodes_total' } ], + output_template => 'Nodes Coordinating: %d', + perfdatas => [ + { value => 'nodes_coordinating_absolute', template => '%d', + min => 0, max => 'nodes_total_absolute' }, + ], + } + }, + { label => 'nodes-master', nlabel => 'nodes.master.count', display_ok => 0, set => { + key_values => [ { name => 'nodes_master' }, { name => 'nodes_total' } ], + output_template => 'Nodes Master: %d', + perfdatas => [ + { value => 'nodes_master_absolute', template => '%d', + min => 0, max => 'nodes_total_absolute' }, + ], + } + }, + { label => 'nodes-ingest', nlabel => 'nodes.ingest.count', display_ok => 0, set => { + key_values => [ { name => 'nodes_ingest' }, { name => 'nodes_total' } ], + output_template => 'Nodes Ingest: %d', + perfdatas => [ + { value => 'nodes_ingest_absolute', template => '%d', + min => 0, max => 'nodes_total_absolute' }, + ], + } + }, + { label => 'indices-total', nlabel => 'indices.total.count', set => { + key_values => [ { name => 'indices_count' } ], + output_template => 'Indices: %d', + perfdatas => [ + { value => 'indices_count_absolute', template => '%d', + min => 0 }, + ], + } + }, + { label => 'shards-total', nlabel => 'shards.total.count', set => { + key_values => [ { name => 'shards_total' } ], + output_template => 'Shards: %d', + perfdatas => [ + { value => 'shards_total_absolute', template => '%d', + min => 0 }, + ], + } + }, + { label => 'shards-active-count', nlabel => 'shards.active.count', display_ok => 0, set => { + key_values => [ { name => 'shards_active' } ], + output_template => 'Shards Active: %d', + perfdatas => [ + { value => 'shards_active_absolute', template => '%d', + min => 0, max => 'shards_total_absolute' }, + ], + } + }, + { label => 'shards-active-percentage', nlabel => 'shards.active.percentage', display_ok => 0, set => { + key_values => [ { name => 'active_shards_percent' } ], + output_template => 'Shards Active: %.2f%%', + perfdatas => [ + { value => 'active_shards_percent_absolute', template => '%.2f', + min => 0, max => 100, unit => '%' }, + ], + } + }, + { label => 'shards-unassigned', nlabel => 'shards.unassigned.count', set => { + key_values => [ { name => 'shards_unassigned' }, { name => 'shards_total' } ], + output_template => 'Shards Unassigned: %d', + perfdatas => [ + { value => 'shards_unassigned_absolute', template => '%d', + min => 0, max => 'shards_total_absolute' }, + ], + } + }, + { label => 'shards-relocating', nlabel => 'shards.relocating.count', display_ok => 0, set => { + key_values => [ { name => 'shards_relocating' }, { name => 'shards_total' } ], + output_template => 'Shards Relocating: %d', + perfdatas => [ + { value => 'shards_relocating_absolute', template => '%d', + min => 0, max => 'shards_total_absolute' }, + ], + } + }, + { label => 'shards-initializing', nlabel => 'shards.initializing.count', display_ok => 0, set => { + key_values => [ { name => 'shards_initializing' }, { name => 'shards_total' } ], + output_template => 'Shards Initializing: %d', + perfdatas => [ + { value => 'shards_initializing_absolute', template => '%d', + min => 0, max => 'shards_total_absolute' }, + ], + } + }, + { label => 'tasks-pending', nlabel => 'tasks.pending.count', set => { + key_values => [ { name => 'tasks_pending' } ], + output_template => 'Tasks Pending: %d', + perfdatas => [ + { value => 'tasks_pending_absolute', template => '%d', + min => 0 }, + ], + } + }, + { label => 'documents-total', nlabel => 'documents.total.count', set => { + key_values => [ { name => 'docs_count' } ], + output_template => 'Documents: %d', + perfdatas => [ + { value => 'docs_count_absolute', template => '%d', + min => 0 }, + ], + } + }, + { label => 'data-size', nlabel => 'data.size.bytes', set => { + key_values => [ { name => 'size_in_bytes' } ], + output_template => 'Data: %s%s', + output_change_bytes => 1, + perfdatas => [ + { value => 'size_in_bytes_absolute', template => '%s', + min => 0, unit => 'B' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => { + "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /yellow/i' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /red/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->change_macros(macros => ['warning_status', 'critical_status']); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $cluster_health = $options{custom}->get(path => '/_cluster/health'); + my $cluster_stats = $options{custom}->get(path => '/_cluster/stats'); + + $self->{global} = { + display => $cluster_stats->{cluster_name}, + status => $cluster_stats->{status}, + nodes_total => $cluster_stats->{nodes}->{count}->{total}, + nodes_data => $cluster_stats->{nodes}->{count}->{data}, + nodes_coordinating => $cluster_stats->{nodes}->{count}->{coordinating_only}, + nodes_master => $cluster_stats->{nodes}->{count}->{master}, + nodes_ingest => $cluster_stats->{nodes}->{count}->{ingest}, + indices_count => $cluster_stats->{indices}->{count}, + shards_total => $cluster_stats->{indices}->{shards}->{total}, + shards_active => $cluster_health->{active_shards}, + shards_unassigned => $cluster_health->{unassigned_shards}, + shards_relocating => $cluster_health->{relocating_shards}, + shards_initializing => $cluster_health->{initializing_shards}, + active_shards_percent => $cluster_health->{active_shards_percent_as_number}, + tasks_pending => $cluster_health->{number_of_pending_tasks}, + docs_count => $cluster_stats->{indices}->{docs}->{count}, + size_in_bytes => $cluster_stats->{indices}->{store}->{size_in_bytes}, + }; +} + +1; + +__END__ + +=head1 MODE + +Check cluster statistics. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^status$' + +=item B<--warning-*> + +Threshold warning. +Can be: 'nodes-total', 'nodes-data', 'nodes-coordinating', +'nodes-master', 'nodes-ingest', 'indices-total', 'shards-total', +'shards-active-count', 'shards-active-percentage', +'shards-unassigned', 'shards-relocating', 'shards-initializing', +'tasks-pending', 'documents-total', 'data-size'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'nodes-total', 'nodes-data', 'nodes-coordinating', +'nodes-master', 'nodes-ingest', 'indices-total', 'shards-total', +'shards-active-count', 'shards-active-percentage', +'shards-unassigned', 'shards-relocating', 'shards-initializing', +'tasks-pending', 'documents-total', 'data-size'. + +=item B<--warning-status> + +Set warning threshold for status (Default: '%{status} =~ /yellow/i') +Can used special variables like: %{status}. + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} =~ /red/i'). +Can used special variables like: %{status}. + +=back + +=cut diff --git a/apps/elasticsearch/restapi/mode/indices.pm b/database/elasticsearch/restapi/mode/indicestatistics.pm similarity index 55% rename from apps/elasticsearch/restapi/mode/indices.pm rename to database/elasticsearch/restapi/mode/indicestatistics.pm index c73510614..b708b6412 100644 --- a/apps/elasticsearch/restapi/mode/indices.pm +++ b/database/elasticsearch/restapi/mode/indicestatistics.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package apps::elasticsearch::restapi::mode::indices; +package database::elasticsearch::restapi::mode::indicestatistics; use base qw(centreon::plugins::templates::counter); @@ -28,9 +28,8 @@ use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold) sub custom_status_output { my ($self, %options) = @_; - my $msg = 'status : ' . $self->{result_values}->{status}; - return $msg; + return "Status '" . $self->{result_values}->{status} . "'"; } sub custom_status_calc { @@ -57,20 +56,49 @@ sub set_counters { closure_custom_threshold_check => \&catalog_status_threshold, } }, - { label => 'active-primary-shards', set => { - key_values => [ { name => 'active_primary_shards' }, { name => 'display' } ], - output_template => 'Active Primary Shards : %s', + { label => 'documents-total', nlabel => 'indice.documents.total.count', set => { + key_values => [ { name => 'docs_count' }, { name => 'display' } ], + output_template => 'Documents: %d', perfdatas => [ - { label => 'active_primary_shards', value => 'active_primary_shards_absolute', template => '%s', + { value => 'docs_count_absolute', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, ], } }, - { label => 'active-shards', set => { - key_values => [ { name => 'active_shards' }, { name => 'display' } ], - output_template => 'Active Shards : %s', + { label => 'data-size-primaries', nlabel => 'indice.data.primaries.size.bytes', set => { + key_values => [ { name => 'size_in_bytes_primaries' }, { name => 'display' } ], + output_template => 'Data Primaries: %s%s', + output_change_bytes => 1, perfdatas => [ - { label => 'active_shards', value => 'active_shards_absolute', template => '%s', + { value => 'size_in_bytes_primaries_absolute', template => '%s', + min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'data-size-total', nlabel => 'indice.data.total.size.bytes', set => { + key_values => [ { name => 'size_in_bytes_total' }, { name => 'display' } ], + output_template => 'Data Total: %s%s', + output_change_bytes => 1, + perfdatas => [ + { value => 'size_in_bytes_total_absolute', template => '%s', + min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'shards-active', nlabel => 'shards.active.count', set => { + key_values => [ { name => 'shards_active' }, { name => 'display' } ], + output_template => 'Shards Active: %d', + perfdatas => [ + { value => 'shards_active_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'shards-unassigned', nlabel => 'shards.unassigned.count', set => { + key_values => [ { name => 'shards_unassigned' }, { name => 'display' } ], + output_template => 'Shards Unassigned: %d', + perfdatas => [ + { value => 'shards_unassigned_absolute', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, ], } @@ -80,17 +108,15 @@ sub set_counters { sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; - $options{options}->add_options(arguments => - { - "elastic-path:s" => { name => 'elastic_path', default => '/_cluster/health?level=indices' }, - "filter-name:s" => { name => 'filter_name' }, - "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /yellow/i' }, - "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /red/i' }, - }); + $options{options}->add_options(arguments => { + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /yellow/i' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /red/i' }, + }); return $self; } @@ -108,23 +134,15 @@ sub prefix_indices_output { return "Indices '" . $options{instance_value}->{display} . "' "; } -sub change_macros { - my ($self, %options) = @_; - - foreach (('warning_status', 'critical_status')) { - if (defined($self->{option_results}->{$_})) { - $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; - } - } -} - sub manage_selection { my ($self, %options) = @_; - + $self->{indices} = {}; - my $result = $options{custom}->get(path => $self->{option_results}->{elastic_path}); + + my $indices = $options{custom}->get(path => '/_cluster/health?level=indices'); + my $stats = $options{custom}->get(path => '/_stats'); - foreach my $indice (keys %{$result->{indices}}) { + foreach my $indice (keys %{$indices->{indices}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $indice !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $indice . "': no matching filter.", debug => 1); @@ -133,9 +151,12 @@ sub manage_selection { $self->{indices}->{$indice} = { display => $indice, - status => $result->{indices}->{$indice}->{status}, - active_primary_shards => $result->{indices}->{$indice}->{active_primary_shards}, - active_shards => $result->{indices}->{$indice}->{active_shards}, + status => $indices->{indices}->{$indice}->{status}, + shards_active => $indices->{indices}->{$indice}->{active_shards}, + shards_unassigned => $indices->{indices}->{$indice}->{unassigned_shards}, + docs_count => $stats->{indices}->{$indice}->{primaries}->{docs}->{count}, + size_in_bytes_primaries => $stats->{indices}->{$indice}->{primaries}->{store}->{size_in_bytes}, + size_in_bytes_total => $stats->{indices}->{$indice}->{total}->{store}->{size_in_bytes}, }; } @@ -151,14 +172,10 @@ __END__ =head1 MODE -Check Elasticsearch indices. +Check indices statistics. =over 8 -=item B<--elastic-path> - -Set path to get Elasticsearch information (Default: '/_cluster/health?level=indices') - =item B<--filter-name> Filter name (can be a regexp). diff --git a/database/elasticsearch/restapi/mode/license.pm b/database/elasticsearch/restapi/mode/license.pm new file mode 100644 index 000000000..052e309c5 --- /dev/null +++ b/database/elasticsearch/restapi/mode/license.pm @@ -0,0 +1,126 @@ +# +# Copyright 2019 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::elasticsearch::restapi::mode::license; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); + +sub custom_status_output { + my ($self, %options) = @_; + my $msg = sprintf("License Status '%s' [type: %s] [issued to: %s] [issue date: %s]", + $self->{result_values}->{status}, + $self->{result_values}->{type}, + $self->{result_values}->{issued_to}, + $self->{result_values}->{issue_date}); + + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; + $self->{result_values}->{issued_to} = $options{new_datas}->{$self->{instance} . '_issued_to'}; + $self->{result_values}->{issue_date} = $options{new_datas}->{$self->{instance} . '_issue_date'}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'status' }, { name => 'type' }, { name => 'issued_to' }, + { name => 'issue_date' } ], + 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 => \&catalog_status_threshold, + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => { + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /active/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->change_macros(macros => ['warning_status', 'critical_status']); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $result = $options{custom}->get(path => '/_license'); + + $self->{global} = { + type => $result->{license}->{type}, + status => $result->{license}->{status}, + issued_to => $result->{license}->{issued_to}, + issue_date => $result->{license}->{issue_date}, + }; +} + +1; + +__END__ + +=head1 MODE + +Check license. + +=over 8 + +=item B<--warning-status> + +Set warning threshold for status (Default: '') +Can used special variables like: %{status}, %{type}, %{issued_to}. + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} !~ /active/i'). +Can used special variables like: %{status}, %{type}, %{issued_to}. + +=back + +=cut diff --git a/database/elasticsearch/restapi/mode/nodestatistics.pm b/database/elasticsearch/restapi/mode/nodestatistics.pm new file mode 100644 index 000000000..f7eeb199b --- /dev/null +++ b/database/elasticsearch/restapi/mode/nodestatistics.pm @@ -0,0 +1,176 @@ +# +# Copyright 2019 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::elasticsearch::restapi::mode::nodestatistics; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'nodes', type => 1, cb_prefix_output => 'prefix_output', + message_multiple => 'All nodes are ok' }, + ]; + + $self->{maps_counters}->{nodes} = [ + { label => 'jvm-heap-usage', nlabel => 'node.jvm.heap.usage.percentage', set => { + key_values => [ { name => 'heap_used_percent' }, { name => 'display' } ], + output_template => 'JVM Heap: %d%%', + perfdatas => [ + { value => 'heap_used_percent_absolute', template => '%d', + min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'jvm-heap-usage-bytes', nlabel => 'node.jvm.heap.usage.bytes', display_ok => 0, set => { + key_values => [ { name => 'heap_used_in_bytes' }, { name => 'heap_max_in_bytes' }, { name => 'display' } ], + output_template => 'JVM Heap Bytes: %s%s', + output_change_bytes => 1, + perfdatas => [ + { value => 'heap_used_in_bytes_absolute', template => '%s', + min => 0, max => 'heap_max_in_bytes_absolute', unit => 'B', label_extra_instance => 1, + instance_use => 'display_absolute' }, + ], + } + }, + { label => 'disk-free', nlabel => 'node.disk.free.bytes', set => { + key_values => [ { name => 'available_in_bytes' }, { name => 'total_in_bytes' }, + { name => 'display' } ], + output_template => 'Free Disk Space: %s%s', + output_change_bytes => 1, + perfdatas => [ + { value => 'available_in_bytes_absolute', template => '%s', + min => 0, max => 'total_in_bytes_absolute', unit => 'B', + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'documents-total', nlabel => 'node.documents.total.count', set => { + key_values => [ { name => 'docs_count' }, { name => 'display' } ], + output_template => 'Documents: %d', + perfdatas => [ + { value => 'docs_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'data-size', nlabel => 'node.data.size.bytes', set => { + key_values => [ { name => 'size_in_bytes' }, { name => 'display' } ], + output_template => 'Data: %s%s', + output_change_bytes => 1, + perfdatas => [ + { value => 'size_in_bytes_absolute', template => '%s', + min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub prefix_output { + my ($self, %options) = @_; + + return "Node '" . $options{instance_value}->{display} . "' "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => { + "filter-name:s" => { name => 'filter_name' }, + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{nodes} = {}; + + my $nodes_stats = $options{custom}->get(path => '/_nodes/stats'); + + foreach my $node (keys %{$nodes_stats->{nodes}}) { + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $node !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $indice . "': no matching filter.", debug => 1); + next; + } + + $self->{nodes}->{$node} = { + display => $nodes_stats->{nodes}->{$node}->{name}, + indices_count => $nodes_stats->{indices}->{count}, + heap_used_percent => $nodes_stats->{nodes}->{$node}->{jvm}->{mem}->{heap_used_percent}, + heap_used_in_bytes => $nodes_stats->{nodes}->{$node}->{jvm}->{mem}->{heap_used_in_bytes}, + heap_max_in_bytes => $nodes_stats->{nodes}->{$node}->{jvm}->{mem}->{heap_max_in_bytes}, + available_in_bytes => $nodes_stats->{nodes}->{$node}->{fs}->{total}->{available_in_bytes}, + total_in_bytes => $nodes_stats->{nodes}->{$node}->{fs}->{total}->{total_in_bytes}, + docs_count => $nodes_stats->{nodes}->{$node}->{indices}->{docs}->{count}, + size_in_bytes => $nodes_stats->{nodes}->{$node}->{indices}->{store}->{size_in_bytes}, + }; + } + + if (scalar(keys %{$self->{nodes}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No nodes found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check nodes statistics. + +=over 8 + +=item B<--filter-name> + +Filter name (can be a regexp). + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='heap' + +=item B<--warning-*> + +Threshold warning. +Can be: 'jvm-heap-usage', 'disk-free', +'documents-total', 'data-size'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'jvm-heap-usage', 'disk-free', +'documents-total', 'data-size'. + +=back + +=cut diff --git a/apps/elasticsearch/restapi/plugin.pm b/database/elasticsearch/restapi/plugin.pm similarity index 64% rename from apps/elasticsearch/restapi/plugin.pm rename to database/elasticsearch/restapi/plugin.pm index df152c9ce..495656726 100644 --- a/apps/elasticsearch/restapi/plugin.pm +++ b/database/elasticsearch/restapi/plugin.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package apps::elasticsearch::restapi::plugin; +package database::elasticsearch::restapi::plugin; use strict; use warnings; @@ -30,12 +30,13 @@ sub new { bless $self, $class; $self->{version} = '0.1'; - %{$self->{modes}} = ( - 'cluster' => 'apps::elasticsearch::restapi::mode::cluster', - 'indices' => 'apps::elasticsearch::restapi::mode::indices', - 'nodes' => 'apps::elasticsearch::restapi::mode::nodes', - ); - $self->{custom_modes}{api} = 'apps::elasticsearch::restapi::custom::api'; + %{$self->{modes}} = ( + 'cluster-statistics' => 'database::elasticsearch::restapi::mode::clusterstatistics', + 'indice-statistics' => 'database::elasticsearch::restapi::mode::indicestatistics', + 'license' => 'database::elasticsearch::restapi::mode::license', + 'node-statistics' => 'database::elasticsearch::restapi::mode::nodestatistics', + ); + $self->{custom_modes}{api} = 'database::elasticsearch::restapi::custom::api'; return $self; } @@ -45,6 +46,6 @@ __END__ =head1 PLUGIN DESCRIPTION -Check elasticsearch through HTTP/REST API. +Check Elasticsearch through HTTP/REST API. =cut