eth-poller plugin and restapi plugin update

This commit is contained in:
Lotfi zaouche 2020-04-08 16:34:15 +00:00
parent eaa301daba
commit c7d97547c8
8 changed files with 720 additions and 227 deletions

View File

@ -0,0 +1,204 @@
#
# Copyright 2020 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 blockchain::parity::ethpoller::custom::api;
use strict;
use warnings;
use centreon::plugins::http;
use DateTime;
use JSON::XS;
sub new {
my ($class, %options) = @_;
my $self = {};
bless $self, $class;
if (!defined($options{output})) {
print "Class Custom: Need to specify 'output' argument.\n";
exit 3;
}
if (!defined($options{options})) {
$options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument.");
$options{output}->option_exit();
}
if (!defined($options{noptions})) {
$options{options}->add_options(arguments => {
"hostname:s" => { name => 'hostname' },
"port:s" => { name => 'port' },
"proto:s" => { name => 'proto' },
"url-path:s" => { name => 'url_path' },
"timeout:s" => { name => 'timeout' },
});
}
$options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1);
$self->{output} = $options{output};
$self->{mode} = $options{mode};
$self->{http} = centreon::plugins::http->new(%options);
return $self;
}
sub set_options {
my ($self, %options) = @_;
$self->{option_results} = $options{option_results};
}
sub set_defaults {
my ($self, %options) = @_;
foreach (keys %{$options{default}}) {
if ($_ eq $self->{mode}) {
for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) {
foreach my $opt (keys %{$options{default}->{$_}[$i]}) {
if (!defined($self->{option_results}->{$opt}[$i])) {
$self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt};
}
}
}
}
}
}
sub check_options {
my ($self, %options) = @_;
$self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef;
$self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8000;
$self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http';
$self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '';
$self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10;
if (!defined($self->{hostname}) || $self->{hostname} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --hostname option.");
$self->{output}->option_exit();
}
return 0;
}
sub build_options_for_httplib {
my ($self, %options) = @_;
$self->{option_results}->{hostname} = $self->{hostname};
$self->{option_results}->{timeout} = $self->{timeout};
$self->{option_results}->{port} = $self->{port};
$self->{option_results}->{proto} = $self->{proto};
$self->{option_results}->{url_path} = $self->{url_path};
$self->{option_results}->{warning_status} = '';
$self->{option_results}->{critical_status} = '';
}
sub settings {
my ($self, %options) = @_;
$self->build_options_for_httplib();
$self->{http}->add_header(key => 'Accept', value => 'application/json');
$self->{http}->set_options(%{$self->{option_results}});
}
sub get_connection_info {
my ($self, %options) = @_;
return $self->{hostname} . ":" . $self->{port};
}
sub get_hostname {
my ($self, %options) = @_;
return $self->{hostname};
}
sub get_port {
my ($self, %options) = @_;
return $self->{port};
}
sub request_api {
my ($self, %options) = @_;
$self->settings;
$self->{output}->output_add(long_msg => "Query URL: '" . $self->{proto} . "://" . $self->{hostname} .
$self->{url_path} . $options{url_path} . "'", debug => 1);
my $content = $self->{http}->request(url_path => $self->{url_path} . $options{url_path});
my $decoded;
eval {
$decoded = JSON::XS->new->utf8->decode($content);
};
if ($@) {
$self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@");
$self->{output}->option_exit();
}
return $decoded;
}
1;
__END__
=head1 NAME
Parity eth-poller Rest API
=head1 SYNOPSIS
Parity eth-poller Rest API custom mode
=head1 REST API OPTIONS
Parity eth-poller Rest API
=over 8
=item B<--hostname>
Parity eth-poller API hostname.
=item B<--port>
API port (Default: 8000)
=item B<--proto>
Specify https if needed (Default: 'http')
=item B<--url-path>
API URL path (Default: '')
=item B<--timeout>
Set HTTP timeout
=back
=head1 DESCRIPTION
B<custom>.
=cut

View File

@ -0,0 +1,98 @@
#
# Copyright 2020 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 blockchain::parity::ethpoller::mode::fork;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'unknown-status:s' => { name => 'unknown_status', default => '' },
'warning-status:s' => { name => 'warning_status', default => '' },
'critical-status:s' => { name => 'critical_status', default => '%{listening} !~ /true/' },
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $result = $options{custom}->request_api(url_path => '/fork');
# use Data::Dumper;
# print Dumper($result);
# Unix time conversion
my $res_timestamp = localtime(hex($result->{last_update}->{timestamp}));
# Alerts management
my $cache = Cache::File->new( cache_root => './parity-eth-poller-cache' );
if (my $cached_timestamp = $cache->get('fork_timestamp')) {
if ($cached_timestamp ne $res_timestamp) {
#alert
}
} else {
$cache->set('fork_timestamp', $res_timestamp);
}
$self->{output}->output_add(severity => 'OK', long_msg => '[Fork]: fork_timestamp: ' . $res_timestamp .
' | fork_occurence: ' . $result->{occurence} . ' | fork_blockNumber: ' . $result->{last_update}->{blockNumber} .
' | fork_in: ' . $result->{last_update}->{in} . ' | fork_out: ' . $result->{last_update}->{out} );
}
1;
__END__
=head1 MODE
Check Parity eth-poller for forks details
=over 8
=item B<--unknown-status>
Set unknown threshold for listening status (Default: '').
=item B<--warning-status>
Set warning threshold for listening status (Default: '').
=item B<--critical-status>
Set critical threshold for listening status (Default: '%{is_mining} !~ /true/').
=item B<--warning-peers> B<--critical-peers>
Warning and Critical threhsold on the number of peer
=back
=cut

View File

@ -0,0 +1,114 @@
#
# Copyright 2020 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 blockchain::parity::ethpoller::mode::stats;
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 => 'global', cb_prefix_output => 'prefix_module_output', type => 0 },
];
$self->{maps_counters}->{global} = [
{ label => 'stats_blockInterval', nlabel => 'parity.network.peers.count', set => {
key_values => [ { name => 'stats_blockInterval' } ],
output_template => "Block interval: %d ",
perfdatas => [
{ label => 'stats_blockInterval', value => 'stats_blockInterval_absolute', template => '%d', min => 0 }
],
}
},
{ label => 'stats_contracts', nlabel => 'eth.poller.stats.contracts.number', set => {
key_values => [ { name => 'stats_contracts' } ],
output_template => "Cumulative contracts: %d ",
perfdatas => [
{ label => 'stats_contracts', value => 'stats_contracts_absolute', template => '%d', min => 0 }
],
}
},
{ label => 'stats_blocks', nlabel => 'eth.poller.stats.blocks.number', set => {
key_values => [ { name => 'stats_blocks' } ],
output_template => "Cumulative blocks: %d ",
perfdatas => [
{ label => 'stats_blocks', value => 'stats_blocks_absolute', template => '%d', min => 0 }
],
}
},
{ label => 'stats_transactions', nlabel => 'eth.poller.stats.transactions.number', set => {
key_values => [ { name => 'stats_transactions' } ],
output_template => "Cumulative transactions: %d ",
perfdatas => [
{ label => 'stats_transactions', value => 'stats_transactions_absolute', template => '%d', min => 0 }
],
}
},
];
}
sub prefix_output {
my ($self, %options) = @_;
return "Stats '";
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
"filter-name:s" => { name => 'filter_name' },
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $result = $options{custom}->request_api(url_path => '/stats');
# use Data::Dumper;
# print Dumper($result);
$self->{global} = { stats_blockInterval => $result->{blockInterval},
stats_contracts => $result->{cumulative}->{contracts},
stats_blocks => $result->{cumulative}->{blocks},
stats_transactions => $result->{cumulative}->{transactions}
};
}
1;
__END__
=head1 MODE
Check Parity eth-poller for accounts tracking
=cut

View File

@ -0,0 +1,130 @@
#
# Copyright 2020 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 blockchain::parity::ethpoller::mode::watchlist;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
"filter-name:s" => { name => 'filter_name' },
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/watchlist');
# use Data::Dumper;
# print Dumper($results);
# Alerts management
my $cache = Cache::File->new( cache_root => './parity-eth-poller-cache' );
if (my $cached_balance = $cache->get('contract_balance')) {
if ($cached_balance != $contract->{balance}) {
#alert
}
} else {
$cache->set('contract_balance', $contract->{balance});
}
foreach my $account (@{$results->{Accounts}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$account->{id} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $account->{id} . "': no matching filter name.", debug => 1);
next;
}
$self->{output}->output_add(severity => 'OK', long_msg => '[Account ' . $account->{id} . ']: label: ' . $account->{label} . ' | nonce: ' . $account->{nonce} .
' | timestamp: ' . localtime(hex($account->{last_update}->{timestamp})) . ' | blockNumber: ' . $account->{last_update}->{blockNumber} .
' | receiver: ' . $account->{last_update}->{receiver} . ' | value: ' . $account->{last_update}->{value} );
}
foreach my $minner (@{$results->{Miners}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$minner->{id} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $minner->{id} . "': no matching filter name.", debug => 1);
next;
}
$self->{output}->output_add(severity => 'OK', long_msg => '[Minner ' . $minner->{id} . ']: label: ' . $minner->{label} . ' | blocks: ' . $minner->{blocks} .
' | timestamp: ' . localtime(hex($minner->{last_update}->{timestamp})) . ' | blockNumber: ' . $minner->{last_update}->{blockNumber} );
}
foreach my $contract (@{$results->{Constracts}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$contract->{id} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $contract->{id} . "': no matching filter name.", debug => 1);
next;
}
$self->{output}->output_add(severity => 'OK', long_msg => '[Contract ' . $contract->{id} . ']: label: ' . $contract->{label} . ' | balance: ' . $contract->{balance} .
' | timestamp: ' . localtime(hex($contract->{last_update}->{timestamp})) . ' | blockNumber: ' . $contract->{last_update}->{blockNumber} .
' | sender: ' . $contract->{last_update}->{sender} . ' | value: ' . $contract->{last_update}->{value} );
}
foreach my $function (@{$results->{Functions}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$function->{id} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $function->{id} . "': no matching filter name.", debug => 1);
next;
}
$self->{output}->output_add(severity => 'OK', long_msg => '[Function ' . $function->{id} . ']: label: ' . $function->{label} . ' | calls: ' . $function->{calls} .
' | timestamp: ' . localtime(hex($function->{last_update}->{timestamp})) . ' | blockNumber: ' . $function->{last_update}->{blockNumber} .
' | sender: ' . $function->{last_update}->{sender} . ' | receiver: ' . $function->{last_update}->{receiver} .
' | value: ' . $function->{last_update}->{value} );
}
foreach my $event (@{$results->{Events}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$event->{id} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $event->{id} . "': no matching filter name.", debug => 1);
next;
}
$self->{output}->output_add(severity => 'OK', long_msg => '[Event ' . $event->{id} . ']: label: ' . $event->{label} . ' | calls: ' . $event->{calls} .
' | timestamp: ' . localtime(hex($event->{last_update}->{timestamp})) . ' | blockNumber: ' . $event->{last_update}->{blockNumber} .
' | sender: ' . $event->{last_update}->{sender} . ' | receiver: ' . $event->{last_update}->{receiver});
}
}
1;
__END__
=head1 MODE
Check Parity eth-poller for accounts tracking
=cut

View File

@ -0,0 +1,50 @@
#
# Copyright 2020 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 blockchain::parity::ethpoller::plugin;
use strict;
use warnings;
use base qw(centreon::plugins::script_custom);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '0.1';
%{$self->{modes}} = (
'watchlist' => 'blockchain::parity::ethpoller::mode::watchlist',
'fork' => 'blockchain::parity::ethpoller::mode::fork',
'stats' => 'blockchain::parity::ethpoller::mode::stats'
);
$self->{custom_modes}{api} = 'blockchain::parity::ethpoller::custom::api';
return $self;
}
1;
__END__
=head1 PLUGIN DESCRIPTION
Check Parity blockchain accounts, contracts and forks from eth-poller with HTTP GET
=cut

View File

@ -40,21 +40,10 @@ sub set_counters {
$self->{maps_counters_type} = [
{ name => 'global', cb_prefix_output => 'prefix_module_output', type => 0 },
{ name => 'peer', cb_prefix_output => 'prefix_module_output', type => 0 },
{ name => 'block', cb_prefix_output => 'prefix_module_output', type => 0 },
{ name => 'sync', cb_prefix_output => 'prefix_module_output', type => 0 }
];
$self->{maps_counters}->{global} = [
{ label => 'coinbase', nlabel => 'parity.eth.client.coinbase', set => {
key_values => [ { name => 'coinbase' } ],
output_template => "Client coinbase is: %s ",
# closure_custom_perfdata => sub { return 0; }
perfdatas => [
{ label => 'client_coinbase', value => 'coinbase_absolute', template => '%s', min => 0 }
],
}
},
{ label => 'gas_price', nlabel => 'parity.eth.gas.price', set => {
key_values => [ { name => 'gas_price' } ],
output_template => "The gas price is: %d wei ",
@ -65,90 +54,47 @@ sub set_counters {
}
];
$self->{maps_counters}->{peer} = [
# { label => 'status', nlabel => 'parity.eth.peers.mining.status', set => {
# key_values => [ { name => 'is_mining' } ],
# output_template => "Client is mining: " . $self->can('custom_mining_status_output'),
# perfdatas => [
# { label => 'is_mining', value => 'is_mining_absolute', template => '%s', min => 0 }
# ],
# }
# },
{ label => 'status', threshold => 0, set => {
key_values => [ { name => 'is_mining' } ],
closure_custom_calc => \&catalog_status_calc,
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold
}
},
{ label => 'hashrate', nlabel => 'parity.eth.node.hashrate', set => {
key_values => [ { name => 'hashrate' } ],
output_template => "Node hashrate is: %d/s ",
perfdatas => [
{ label => 'node_hashrate', value => 'hashrate_absolute', template => '%d', min => 0 }
],
}
},
];
$self->{maps_counters}->{block} = [
{ label => 'block_number', nlabel => 'parity.eth.block.number', set => {
key_values => [ { name => 'block_number' } ],
output_template => "Most recent block number is: %d ",
closure_custom_perfdata => sub { return 0; }
# perfdatas => [
# { label => 'block_number', value => 'block_number_absolute', template => '%d', min => 0 }
# ],
}
},
{ label => 'block_time', nlabel => 'parity.eth.block.time', set => {
key_values => [ { name => 'block_time' } ],
output_template => "Block time is: %s ",
closure_custom_perfdata => sub { return 0; }
# perfdatas => [
# { label => 'block_time', value => 'block_time_absolute', template => '%s', min => 0 }
# ],
}
},
];
$self->{maps_counters}->{sync} = [
{ label => 'sync_start', nlabel => 'parity.eth.sync.start.block', set => {
key_values => [ { name => 'sync_start' } ],
output_template => "Sync start block number is: %d ",
closure_custom_perfdata => sub { return 0; }
# perfdatas => [
# { label => 'sync_start', value => 'sync_start_absolute', template => '%d', min => 0 }
# ],
}
},
{ label => 'sync_current', nlabel => 'parity.eth.sync.current.block', set => {
key_values => [ { name => 'sync_current' } ],
output_template => "Sync current block number is: %d ",
closure_custom_perfdata => sub { return 0; }
# perfdatas => [
# { label => 'sync_current', value => 'sync_current_absolute', template => '%d', min => 0 }
# ],
}
},
{ label => 'sync_highest', nlabel => 'parity.eth.sync.highest.block', set => {
key_values => [ { name => 'sync_highest' } ],
output_template => "Sync highest block number is: %d ",
# closure_custom_perfdata => sub { return 0; }
{ label => 'block_size', nlabel => 'parity.eth.block.size', set => {
key_values => [ { name => 'block_size' } ],
output_template => "Most recent block size: %d ",
perfdatas => [
{ label => 'sync_highest', value => 'sync_highest_absolute', template => '%d', min => 0 }
{ label => 'block_size', value => 'block_size_absolute', template => '%d', min => 0 }
],
}
},
{ label => 'sync', nlabel => 'parity.eth.sync.ratio', set => {
key_values => [ { name => 'sync' } ],
output_template => "Sync ratio is: %d%% ",
{ label => 'block_transactions', nlabel => 'parity.eth.block.transactions.number', set => {
key_values => [ { name => 'block_transactions' } ],
output_template => "Block transactions number: %d ",
perfdatas => [
{ label => 'sync', value => 'sync_absolute', template => '%d', min => 0 }
{ label => 'block_transactions', value => 'block_transactions_absolute', template => '%d', min => 0 }
],
}
}
},
{ label => 'block_gas', nlabel => 'parity.eth.block.gas', set => {
key_values => [ { name => 'block_gas' } ],
output_template => "Block gas: %d ",
perfdatas => [
{ label => 'block_gas', value => 'block_gas_absolute', template => '%d', min => 0 }
],
}
},
{ label => 'block_difficulty', nlabel => 'parity.eth.block.difficulty', set => {
key_values => [ { name => 'block_difficulty' } ],
output_template => "Block difficulty: %f ",
perfdatas => [
{ label => 'block_difficulty', value => 'block_difficulty_absolute', template => '%f', min => 0 }
],
}
},
{ label => 'block_uncles', nlabel => 'parity.eth.block.difficulty', set => {
key_values => [ { name => 'block_uncles' } ],
output_template => "Block uncles: %d ",
perfdatas => [
{ label => 'block_uncles', value => 'block_uncles_absolute', template => '%d', min => 0 }
],
}
},
];
}
@ -190,32 +136,55 @@ sub manage_selection {
{ method => 'eth_syncing', params => [], id => "7", jsonrpc => "2.0" } ];
my $result = $options{custom}->request_api(method => 'POST', query_form_post => $query_form_post);
my $gas_price = hex(@{$result}[2]->{result});
# use Data::Dumper;
# print Dumper($result);
# my $length = scalar(@{$$result[5]->{result}->{transactions}});
# print Dumper($result) ;
# conditional formating:
my $res_sync = @{$result}[6]->{result} ? hex((@{$result}[6]->{result}->{currentBlock} / @{$result}[6]->{result}->{highestBlock})) * 100 : 100;
my $res_startingBlock = $res_sync != 100 ? hex(@{$result}[6]->{result}->{startingBlock}) : undef;
my $res_currentBlock = $res_sync != 100 ? hex(@{$result}[6]->{result}->{currentBlock}) : undef;
my $res_highestBlock = $res_sync != 100 ? hex(@{$result}[6]->{result}->{highestBlock}) : undef;
my $res_startingBlock = $res_sync != 100 ? hex(@{$result}[6]->{result}->{startingBlock}) : 'none';
my $res_currentBlock = $res_sync != 100 ? hex(@{$result}[6]->{result}->{currentBlock}) : 'none';
my $res_highestBlock = $res_sync != 100 ? hex(@{$result}[6]->{result}->{highestBlock}) : 'none';
# Unix time conversion
my $res_timestamp = localtime(hex(@{$result}[5]->{result}->{timestamp}));
# Alerts management
my $cache = Cache::File->new( cache_root => './parity-restapi-cache' );
$self->{global} = { coinbase => @{$result}[1]->{result},
gas_price => hex(@{$result}[2]->{result}) };
if (my $cached_sync = $cache->get('node_sync')) {
if ($cached_sync == 100 && $res_sync < 100) {
#alert
}
} else {
$cache->set('node_sync', $res_sync);
}
$self->{block} = { block_number => defined @{$result}[4]->{result} ? hex(@{$result}[4]->{result}) : 0,
block_time => $res_timestamp };
if (my $cached_price = $cache->get('gas_price')) {
if ($cached_price != $gas_price) {
#alert
}
} else {
$cache->set('gas_price', $gas_price);
}
$self->{sync} = { sync_start => $res_startingBlock,
sync_current => $res_currentBlock,
sync_highest => $res_highestBlock,
sync => $res_sync };
$self->{global} = { gas_price => $gas_price };
$self->{peer} = { is_mining => @{$result}[0]->{result},
hashrate => hex(@{$result}[3]->{result}) };
$self->{block} = { block_size => hex(@{$result}[5]->{result}->{size}),
block_gas => hex(@{$result}[5]->{result}->{gasUsed}),
block_difficulty => hex(@{$result}[5]->{result}->{totalDifficulty}),
block_uncles => scalar(@{$$result[5]->{result}->{uncles}}),
block_transactions => scalar(@{$$result[5]->{result}->{transactions}})};
$self->{output}->output_add(severity => 'OK', long_msg => '[Node status] is_mining: ' . @{$result}[0]->{result} . ' | sync_start: ' . $res_startingBlock .
' | sync_current: ' . $res_currentBlock . ' | sync_highest: ' . $res_highestBlock . ' | sync: ' . $res_sync . '%%');
$self->{output}->output_add(severity => 'OK', long_msg => '[Client] coinbase: ' . @{$result}[1]->{result});
$self->{output}->output_add(severity => 'OK', long_msg => '[Global] hashrate: ' . hex(@{$result}[3]->{result}) .
' | block_number: ' . (defined @{$result}[4]->{result} ? hex(@{$result}[4]->{result}) : 0));
$self->{output}->output_add(severity => 'OK', long_msg => '[Last block] block_time: ' . localtime(hex(@{$result}[5]->{result}->{timestamp})) . ' | block_gas_limit: ' . hex(@{$result}[5]->{result}->{gasLimit}) .
' | block_miner: ' . @{$result}[5]->{result}->{miner} . ' | block_hash: ' . @{$result}[5]->{result}->{hash} .
' | last_block_number: ' . hex(@{$result}[5]->{result}->{number}));
}
1;

View File

@ -43,15 +43,7 @@ sub set_counters {
];
$self->{maps_counters}->{network} = [
{ label => 'status', threshold => 0, set => {
key_values => [ { name => 'listening' } ],
closure_custom_calc => \&catalog_status_calc,
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold
}
},
{ label => 'peers', nlabel => 'parity.network.peers.count', set => {
{ label => 'peers', nlabel => 'parity.network.peers.count', set => {
key_values => [ { name => 'peers' } ],
output_template => "connected peers: %s ",
perfdatas => [
@ -96,9 +88,24 @@ sub manage_selection {
my $result = $options{custom}->request_api(method => 'POST', query_form_post => $query_form_post);
$self->{network} = { listening => @{$result}[0]->{result},
peers => hex(@{$result}[1]->{result}) };
my $peer_count = hex(@{$result}[1]->{result});
# Alerts management
my $cache = Cache::File->new( cache_root => './parity-restapi-cache' );
if (my $cached_count = $cache->get('peers_count')) {
if ($peer_count < $cached_count) {
#alert
} elsif ($peer_count > $cached_count) {
#alert
}
} else {
$cache->set('peers_count', $peer_count);
}
$self->{network} = { peers => hex(@{$result}[1]->{result}) };
$self->{output}->output_add(long_msg => "[Node] is_listening: " . $peer_count, severity => 'OK');
}
1;

View File

@ -24,108 +24,18 @@ use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use Cache::File;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc);
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
# { name => 'global', cb_prefix_output => 'prefix_module_output', type => 0 },
{ name => 'node', cb_prefix_output => 'prefix_module_output', type => 0 },
{ name => 'mempool', cb_prefix_output => 'prefix_module_output', type => 0 },
{ name => 'network', cb_prefix_output => 'prefix_module_output', type => 0 }
];
$self->{maps_counters}->{global} = [
{ label => 'parity_version', nlabel => 'parity.version', threshold => 0, set => {
key_values => [ { name => 'parity_version' } ],
output_template => "Parity version is: %s ",
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => sub { return 0; }
# perfdatas => [
# { label => 'parity_version', value => 'parity_version_absolute', template => '%s', min => 0 }
# ],
}
},
{ label => 'parity_version_hash', nlabel => 'parity.version.hash', set => {
key_values => [ { name => 'parity_version_hash' } ],
output_template => "Parity version hash is: %s ",
closure_custom_perfdata => sub { return 0; }
# perfdatas => [
# { label => 'parity_version_hash', value => 'parity_version_hash_absolute', template => '%s', min => 0 }
# ],
}
},
{ label => 'chain_name', nlabel => 'parity.chain.name', set => {
key_values => [ { name => 'chain_name' } ],
output_template => "Chain name is: %s ",
closure_custom_perfdata => sub { return 0; }
# perfdatas => [
# { label => 'chain_name', value => 'chain_name_absolute', template => '%s', min => 0 }
# ],
}
},
];
$self->{maps_counters}->{node} = [
{ label => 'enode', nlabel => 'parity.node.enode.uri', threshold => 0, set => {
key_values => [ { name => 'enode' } ],
output_template => "Node enode URI: %s ",
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => sub { return 0; }
# perfdatas => [
# { label => 'enode', value => 'enode_absolute', template => '%s', min => 0 }
# ],
}
},
{ label => 'node_name', nlabel => 'parity.node.name', set => {
key_values => [ { name => 'node_name' } ],
output_template => "Node name: %s ",
closure_custom_perfdata => sub { return 0; }
# perfdatas => [
# { label => 'node_name', value => 'node_name_absolute', template => '%s', min => 0 }
# ],
}
}
];
$self->{maps_counters}->{network} = [
{ label => 'peers_connected', nlabel => 'parity.peers.connected', set => {
key_values => [ { name => 'peers_connected' } ],
output_template => "Number of connected peers: %d ",
perfdatas => [
{ label => 'peers_connected', value => 'peers_connected_absolute', template => '%d', min => 0 }
],
}
},
{ label => 'peers_max', nlabel => 'parity.peers.max.connected', set => {
key_values => [ { name => 'peers_max' } ],
output_template => "Maximum number of connected peers: %d ",
perfdatas => [
{ label => 'peers_max', value => 'peers_max_absolute', template => '%d', min => 0 }
],
}
},
{ label => 'peers', nlabel => 'parity.peers', set => {
key_values => [ { name => 'peers' } ],
output_template => "Peers: %d ",
perfdatas => [
{ label => 'peers', value => 'peers_absolute', template => '%d', min => 0 }
],
}
}
];
{ name => 'mempool', cb_prefix_output => 'prefix_module_output', type => 0 }
];
$self->{maps_counters}->{mempool} = [
{ label => 'pending_transactions', nlabel => 'parity.pending.transactions', set => {
key_values => [ { name => 'pending_transactions' } ],
output_template => "Pending transactions: %d ",
perfdatas => [
{ label => 'pending_transactions', value => 'pending_transactions_absolute', template => '%d', min => 0 }
],
}
},
{ label => 'mempool', nlabel => 'parity.mempol.capacity', set => {
{ label => 'mempool', nlabel => 'parity.mempol.usage', set => {
key_values => [ { name => 'mempool' } ],
output_template => "Mempool: %d %% ",
perfdatas => [
@ -172,35 +82,46 @@ sub manage_selection {
{ method => 'parity_netPeers', params => [], id => "4", jsonrpc => "2.0" },
{ method => 'parity_enode', params => [], id => "5", jsonrpc => "2.0" },
{ method => 'parity_nodeName', params => [], id => "6", jsonrpc => "2.0" },
{ method => 'parity_transactionsLimit', params => [], id => "7", jsonrpc => "2.0" } ]; # parity_transactionsLimit could be done once, at the beginning of the process
{ method => 'parity_transactionsLimit', params => [], id => "7", jsonrpc => "2.0" } ]; #TO CHECK parity_transactionsLimit could be done once, at the beginning of the process
my $result = $options{custom}->request_api(method => 'POST', query_form_post => $query_form_post);
use Data::Dumper;
# print Dumper($result);
# Parity version construction
my $res_parity_version = @{$result}[0]->{result}->{version}->{major} . '.' . @{$result}[0]->{result}->{version}->{minor} . '.' . @{$result}[0]->{result}->{version}->{patch};
# Alerts management
my $cache = Cache::File->new( cache_root => './parity-restapi-cache' );
if (my $cached_version = $cache->get('parity_version')) {
if ($res_parity_version ne $cached_version) {
#alert
}
} else {
$cache->set('parity_version', $res_parity_version);
}
if (my $cached_name = $cache->get('chain_name')) {
if ($cached_name ne @{$result}[1]->{result}) {
#alert
}
} else {
$cache->set('chain_name', @{$result}[1]->{result});
}
# use Data::Dumper;
# print Dumper($res_parity_version);
# print Dumper($result);
$self->{output}->output_add(long_msg => "[config] chain name: " . @{$result}[1]->{result} . " parity version: " . $res_parity_version . " version_hash: " . @{$result}[0]->{result}->{hash},
severity => 'OK');
# $self->{global} = { parity_version => $res_parity_version,
# parity_version_hash => @{$result}[0]->{result}->{hash},
# chain_name => @{$result}[1]->{result} };
# $self->{node} = { enode => @{$result}[4]->{result},
# node_name => @{$result}[5]->{result} };
$self->{network} = { peers_connected => @{$result}[3]->{result}->{connected},
peers_max => @{$result}[3]->{result}->{max},
peers => length(@{$result}[3]->{result}->{peers}) };
$self->{mempool} = { pending_transactions => length(@{$result}[2]->{result}),
mempool => @{$result}[2]->{result} / @{$result}[6]->{result} * 100 };
$self->{output}->output_add(long_msg => "[config] chain name: " . @{$result}[1]->{result} . " | parity version: " . $res_parity_version . " | version_hash: "
. @{$result}[0]->{result}->{hash}, severity => 'OK');
$self->{output}->output_add(long_msg => "[Network] peers_connected: " . @{$result}[3]->{result}->{connected} . " | peers_max: " . @{$result}[3]->{result}->{max} . " | peers: "
. scalar(@{$$result[3]->{result}->{peers}}), severity => 'OK');
$self->{output}->output_add(long_msg => "[Node] node_name: " . @{$result}[5]->{result} . " | enode: " . @{$result}[4]->{result} , severity => 'OK');
$self->{output}->output_add(long_msg => "[Node] pending_transactions: " . scalar(@{$$result[2]->{result}}), severity => 'OK');
$self->{mempool} = { mempool => scalar(@{$$result[2]->{result}}) / @{$result}[6]->{result} * 100 }; #TO CHECK division entière
}
1;