From 33d2c1209ae6928576ab706e49696d33e9f90c13 Mon Sep 17 00:00:00 2001 From: Benjamin Rokseth Date: Thu, 23 Jan 2014 15:54:07 +0100 Subject: [PATCH 1/3] first draft --- check_json.pl | 80 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/check_json.pl b/check_json.pl index dd13c05..98b6624 100755 --- a/check_json.pl +++ b/check_json.pl @@ -3,21 +3,24 @@ use warnings; use strict; use LWP::UserAgent; -use JSON 'decode_json'; +use JSON; use Nagios::Plugin; use Data::Dumper; my $np = Nagios::Plugin->new( - usage => "Usage: %s [ -v|--verbose ] [-U ] [-t ] " + usage => "Usage: %s -U -a|--attribute [-t|--timeout ] " . "[ -c|--critical ] [ -w|--warning ] " - . "[ -a | --attribute ] ", - version => '0.1', + . "[ -a|--attribute ] " + . "[ -D|--divisor ] " + . "[ -p|--perfvars ]", + version => '0.2', blurb => 'Nagios plugin to check JSON attributes via http(s)', extra => "\nExample: \n" . "check_json.pl -U http://192.168.5.10:9332/local_stats -a '{shares}->{dead}' -w :5 -c :10", url => 'https://github.com/c-kr/check_json', plugin => 'check_json', timeout => 15, + shortname => "Check JSON status API", ); # add valid command line options and build them into your usage/help documentation. @@ -37,29 +40,34 @@ $np->add_arg( ); $np->add_arg( spec => 'warning|w=s', - help => '-w, --warning INTEGER:INTEGER . See ' + help => '-w, --warning INTEGER:INTEGER . See ' . 'http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT ' . 'for the threshold format. ', ); $np->add_arg( spec => 'critical|c=s', - help => '-c, --critical INTEGER:INTEGER . See ' + help => '-c, --critical INTEGER:INTEGER . See ' . 'http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT ' . 'for the threshold format. ', ); +$np->add_arg( + spec => 'perfvars|p=s', + help => '-p, --perfvars INTEGER:INTEGER . CSV list of fields from JSON response to include in perfdata ', +); -# Parse @ARGV and process standard arguments (e.g. usage, help, version) +## Parse @ARGV and process standard arguments (e.g. usage, help, version) $np->getopts; - +if ($np->opts->verbose) { (print Dumper ($np))}; ## GET URL my $ua = LWP::UserAgent->new; -$ua->agent('check_json/0.1'); +$ua->agent('check_json/0.2'); $ua->default_header('Accept' => 'application/json'); $ua->protocols_allowed( [ 'http', 'https'] ); $ua->parse_head(0); $ua->timeout($np->opts->timeout); +if ($np->opts->verbose) { (print Dumper ($ua))}; my $response = ($ua->get($np->opts->URL)); @@ -71,32 +79,60 @@ if ($response->is_success) { $np->nagios_exit(CRITICAL, "Connection failed: ".$response->status_line); } +## Parse JSON my $json_response = decode_json($response->content); if ($np->opts->verbose) { (print Dumper ($json_response))}; -my $value; -my $exec = '$value = $json_response->'.$np->opts->attribute; -if ($np->opts->verbose) {print "EXEC is: $exec \n"}; -eval $exec; +my $check_value; +my $check_value_str = '$check_value = $json_response->'.$np->opts->attribute; -if (!defined $value) { +# if ($np->opts->verbose) { (print Dumper ($exec))}; +eval $check_value_str; + +#$attribute_value = $json_response->{eval $np->opts->attribute}; + +if (!defined $check_value) { $np->nagios_exit(UNKNOWN, "No value received"); } if (defined $np->opts->divisor) { - $value = $value/$np->opts->divisor; + $check_value = $check_value/$np->opts->divisor; } -my $result = $np->check_threshold($value); +my $result = $np->check_threshold($check_value); -$np->add_perfdata( - label => 'value', - value => $value, - threshold => $np->threshold(), -); +my @perfdata; + +# routine to add perfdata from JSON response based on a loop of keys given in perfvals (csv) +if ($np->opts->perfvars) { + foreach my $key (split(',', $np->opts->perfvars)) { + # use last element of key as label + my $label = (split('->', $key))[-1]; + $label =~ s/[^a-zA-Z0-9_-]//g ; + my $perf_val; + $perf_val = eval '$json_response->'.$key; + print Dumper ("JSON key: ".$label.", JSON val: " . eval $perf_val); + if ($np->opts->verbose) { print Dumper ("JSON key: ".$label.", JSON val: " . eval $perf_val) }; + if ( defined($perf_val) ) { + push(@perfdata, {label => lc $label, value => $perf_val}); + $np->add_perfdata( + label => lc $label, + value => $perf_val, + #threshold => $np->threshold(), + ); + } + } +} + +sub pp { + my $h = shift(); + qq[{${\(join',',map"$_=>$h->{$_}",keys%$h)}}] +} + +print Dumper (@perfdata); $np->nagios_exit( return_code => $result, - message => $value, + message => pp @perfdata, ); From b716491160ed7a1e8f7bd31d24f29fd0b02ef3ff Mon Sep 17 00:00:00 2001 From: Benjamin Rokseth Date: Thu, 23 Jan 2014 22:38:12 +0100 Subject: [PATCH 2/3] added performance stats and cleaned up code --- README.md | 18 +++++++++++---- check_json.pl | 64 ++++++++++++++++++++++++++------------------------- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 0aed0a1..92814a8 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,22 @@ check_json Nagios plugin to check JSON attributes via http(s). -This Plugin is a fork of the existing JSON Plugin from https://github.com/bbuchalter/check_json with the enhancements of using the Nagios::Plugin Perl Module, allowing to use thresholds and performancedata collection from various json attributes. +This Plugin is a fork of the existing JSON Plugin from https://github.com/bbuchalter/check_json with the enhancements of using the Nagios::Plugin Perl Module, allowing to use thresholds and performance data collection from various json attributes. -Usage: `check_json -U -a [ -v|--verbose ] [-t ] [ -c|--critical ] [ -w|--warning ]` +Performance data is also enhanced to extract performance data compliant to Nagios and Graphite standards. One attribute is selected for thresholds check, multiple others can be added for extracting performance data. This plugin is aimed at simplifying Nagios, Icinga & Icinga2 polling of JSON status APIs. + +Usage: +``` +check_json -u|--url -a|--attribute [ -c|--critical ] [ -w|--warning ] [ -p|--perfvars ] [ -t|--timeout ] [ -d|--divisor ] [ -h|--help ] +``` Example: +``` +./check_json.pl --url http://192.168.5.10:9332/local_stats --attribute '{shares}->{dead_shares}' --warning :5 --critical :10 --perfvars '{shares}->{dead_shares},{shares}->{live_shares},{clients}->{clients_connected}' +``` -`check_json.pl -U http://192.168.5.10:9332/local_stats -a '{shares}->{dead}' -w :5 -c :10` +Result: +``` +Check JSON status API OK - dead_shares: 2, live_shares: 12, clients_connected: 234 | dead_shares=2;5;10 live_shares=12 clients_connected=234 +``` -JSON OK - 2 | value=2;; diff --git a/check_json.pl b/check_json.pl index 98b6624..91466e3 100755 --- a/check_json.pl +++ b/check_json.pl @@ -8,15 +8,17 @@ use Nagios::Plugin; use Data::Dumper; my $np = Nagios::Plugin->new( - usage => "Usage: %s -U -a|--attribute [-t|--timeout ] " + usage => "Usage: %s -u|--url -a|--attribute " . "[ -c|--critical ] [ -w|--warning ] " - . "[ -a|--attribute ] " - . "[ -D|--divisor ] " - . "[ -p|--perfvars ]", + . "[ -p|--perfvars ] " + . "[ -t|--timeout ] " + . "[ -d|--divisor ] " + . "[ -h|--help ] ", version => '0.2', blurb => 'Nagios plugin to check JSON attributes via http(s)', extra => "\nExample: \n" - . "check_json.pl -U http://192.168.5.10:9332/local_stats -a '{shares}->{dead}' -w :5 -c :10", + . "check_json.pl --url http://192.168.5.10:9332/local_stats --attribute '{shares}->{dead}' " + . "--warning :5 --critical :10 --perfvars '{shares}->{dead},{shares}->{live}'", url => 'https://github.com/c-kr/check_json', plugin => 'check_json', timeout => 15, @@ -25,8 +27,8 @@ my $np = Nagios::Plugin->new( # add valid command line options and build them into your usage/help documentation. $np->add_arg( - spec => 'URL|U=s', - help => '-U, --URL http://192.168.5.10:9332/local_stats', + spec => 'url|u=s', + help => '-u, --url (eg. http://192.168.5.10:9332/local_stats}', required => 1, ); $np->add_arg( @@ -35,8 +37,8 @@ $np->add_arg( required => 1, ); $np->add_arg( - spec => 'divisor|D=i', - help => '-D, --divisor 1000000', + spec => 'divisor|d=i', + help => '-d, --divisor 1000000', ); $np->add_arg( spec => 'warning|w=s', @@ -52,7 +54,8 @@ $np->add_arg( ); $np->add_arg( spec => 'perfvars|p=s', - help => '-p, --perfvars INTEGER:INTEGER . CSV list of fields from JSON response to include in perfdata ', + help => '-p, --perfvars . CSV list of fields from JSON response to include in perfdata ' + . '{shares}->{dead},{shares}->{live}', ); ## Parse @ARGV and process standard arguments (e.g. usage, help, version) @@ -69,7 +72,7 @@ $ua->parse_head(0); $ua->timeout($np->opts->timeout); if ($np->opts->verbose) { (print Dumper ($ua))}; -my $response = ($ua->get($np->opts->URL)); +my $response = ($ua->get($np->opts->url)); if ($response->is_success) { if (!($response->header("content-type") =~ 'application/json')) { @@ -86,11 +89,9 @@ if ($np->opts->verbose) { (print Dumper ($json_response))}; my $check_value; my $check_value_str = '$check_value = $json_response->'.$np->opts->attribute; -# if ($np->opts->verbose) { (print Dumper ($exec))}; +if ($np->opts->verbose) { (print Dumper ($check_value_str))}; eval $check_value_str; -#$attribute_value = $json_response->{eval $np->opts->attribute}; - if (!defined $check_value) { $np->nagios_exit(UNKNOWN, "No value received"); } @@ -101,38 +102,39 @@ if (defined $np->opts->divisor) { my $result = $np->check_threshold($check_value); -my @perfdata; +my @statusmsg; # routine to add perfdata from JSON response based on a loop of keys given in perfvals (csv) if ($np->opts->perfvars) { foreach my $key (split(',', $np->opts->perfvars)) { # use last element of key as label my $label = (split('->', $key))[-1]; + # make label ascii compatible $label =~ s/[^a-zA-Z0-9_-]//g ; my $perf_val; $perf_val = eval '$json_response->'.$key; - print Dumper ("JSON key: ".$label.", JSON val: " . eval $perf_val); - if ($np->opts->verbose) { print Dumper ("JSON key: ".$label.", JSON val: " . eval $perf_val) }; + if ($np->opts->verbose) { print Dumper ("JSON key: ".$label.", JSON val: " . $perf_val) }; if ( defined($perf_val) ) { - push(@perfdata, {label => lc $label, value => $perf_val}); - $np->add_perfdata( - label => lc $label, - value => $perf_val, - #threshold => $np->threshold(), - ); + push(@statusmsg, "$label: $perf_val"); + # add threshold if attribute option matches key + if ($key eq $np->opts->attribute) { + $np->add_perfdata( + label => lc $label, + value => $perf_val, + threshold => $np->threshold(), + ); + } else { + $np->add_perfdata( + label => lc $label, + value => $perf_val, + ); + } } } } -sub pp { - my $h = shift(); - qq[{${\(join',',map"$_=>$h->{$_}",keys%$h)}}] -} - -print Dumper (@perfdata); - $np->nagios_exit( return_code => $result, - message => pp @perfdata, + message => join(', ', @statusmsg), ); From caeedf6435b574353d2d6808f8267bb94b4fa0da Mon Sep 17 00:00:00 2001 From: Benjamin Rokseth Date: Thu, 23 Jan 2014 23:46:19 +0100 Subject: [PATCH 3/3] small fix on divisor on check_value --- check_json.pl | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/check_json.pl b/check_json.pl index 91466e3..638e880 100755 --- a/check_json.pl +++ b/check_json.pl @@ -111,22 +111,23 @@ if ($np->opts->perfvars) { my $label = (split('->', $key))[-1]; # make label ascii compatible $label =~ s/[^a-zA-Z0-9_-]//g ; - my $perf_val; - $perf_val = eval '$json_response->'.$key; - if ($np->opts->verbose) { print Dumper ("JSON key: ".$label.", JSON val: " . $perf_val) }; - if ( defined($perf_val) ) { - push(@statusmsg, "$label: $perf_val"); + my $perf_value; + $perf_value = eval '$json_response->'.$key; + if ($np->opts->verbose) { print Dumper ("JSON key: ".$label.", JSON val: " . $perf_value) }; + if ( defined($perf_value) ) { # add threshold if attribute option matches key if ($key eq $np->opts->attribute) { + push(@statusmsg, "$label: $check_value"); $np->add_perfdata( label => lc $label, - value => $perf_val, + value => $check_value, threshold => $np->threshold(), ); } else { + push(@statusmsg, "$label: $perf_value"); $np->add_perfdata( label => lc $label, - value => $perf_val, + value => $perf_value, ); } }