Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ check_json -u|--url <URL> -a|--attribute <attribute> [ -c|--critical <threshold>

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 --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}' -o '{shares}->*->{name},'
```

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
```

Outputvars: It accepts also wildcards in the middle of the tree.

Requirements
============

Perl JSON package

* Debian / Ubuntu : libjson-perl libnagios-plugin-perl libwww-perl
* RHEL / CentOS : perl-Nagios-Plugin perl-JSON perl-HTTP-Parser
94 changes: 84 additions & 10 deletions check_json.pl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
use strict;
use HTTP::Request::Common;
use LWP::UserAgent;
use URI::URL;
use JSON;
use Nagios::Plugin;
use Data::Dumper;

my $version = '0.7';

my $np = Nagios::Plugin->new(
usage => "Usage: %s -u|--url <http://user:pass\@host:port/url> -a|--attributes <attributes> "
. "[ -c|--critical <thresholds> ] [ -w|--warning <thresholds> ] "
Expand All @@ -18,9 +21,12 @@
. "[ -d|--divisor <divisor> ] "
. "[ -m|--metadata <content> ] "
. "[ -T|--contenttype <content-type> ] "
. "[ -A|--auth <username:password> ] "
. "[ --ignoressl ] "
. "[ -A|--hattrib <value> ] "
. "[ -C|--hcon <value> ] "
. "[ -h|--help ] ",
version => '0.5',
version => $version,
blurb => 'Nagios plugin to check JSON attributes via http(s)',
extra => "\nExample: \n"
. "check_json.pl --url http://192.168.5.10:9332/local_stats --attributes '{shares}->{dead}' "
Expand Down Expand Up @@ -94,21 +100,46 @@
. "Content-type accepted if different from application/json ",
);

$np->add_arg(
spec => 'auth|A=s',
help => '-A, --auth realm:username:password',
required => 0,
);

$np->add_arg(
spec => 'ignoressl',
help => "--ignoressl\n Ignore bad ssl certificates",
);

$np->add_arg(
spec => 'hattrib|A=s',
help => "-A, --header-attrib STRING \n "
. "Additional Header attribute.",
);
$np->add_arg(
spec => 'hcon|C=s',
help => "-C, --header-content STRING \n "
. "Additional Header content.",
);

## Parse @ARGV and process standard arguments (e.g. usage, help, version)
$np->getopts;
if ($np->opts->verbose) { (print Dumper ($np))};

if ($np->opts->hattrib and not $np->opts->hcon) {
$np->nagios_exit(UNKNOWN,"Additional Header attribute provided without Additional Header content");
}
if ( not $np->opts->hattrib and $np->opts->hcon) {
$np->nagios_exit(UNKNOWN,"Additional Header content provided without Additional Header attribule");
}

## GET URL
my $ua = LWP::UserAgent->new;

$ua->env_proxy;
$ua->agent('check_json/0.5');
$ua->agent('check_json/'. $version);
$ua->default_header('Accept' => 'application/json');
$ua->default_header($np->opts->hattrib => $np->opts->hcon) if ( $np->opts->hattrib and $np->opts->hcon );
$ua->protocols_allowed( [ 'http', 'https'] );
$ua->parse_head(0);
$ua->timeout($np->opts->timeout);
Expand All @@ -117,6 +148,12 @@
$ua->ssl_opts(verify_hostname => 0, SSL_verify_mode => 0x00);
}

if ($np->opts->auth) {
my @credentials = split(':', $np->opts->auth);
my $url = url $np->opts->url;
$ua->credentials($url->host . ':' . $url->port, $credentials[0], $credentials[1], $credentials[2]);
}

if ($np->opts->verbose) { (print Dumper ($ua))};

my $response;
Expand All @@ -139,8 +176,14 @@
if ($np->opts->verbose) { (print Dumper ($json_response))};

my @attributes = split(',', $np->opts->attributes);
my @warning = split(',', $np->opts->warning);
my @critical = split(',', $np->opts->critical);
my @warning;
if ($np->opts->warning) {
@warning = split(',', $np->opts->warning);
}
my @critical;
if ($np->opts->critical) {
@critical = split(',', $np->opts->critical);
}
my @divisor = $np->opts->divisor ? split(',',$np->opts->divisor) : () ;
my %attributes = map { $attributes[$_] => { warning => $warning[$_] , critical => $critical[$_], divisor => ($divisor[$_] or 0) } } 0..$#attributes;

Expand All @@ -152,7 +195,7 @@
foreach my $attribute (sort keys %attributes){
my $check_value;
my $check_value_str = '$check_value = $json_response->'.$attribute;

if ($np->opts->verbose) { (print Dumper ($check_value_str))};
eval $check_value_str;

Expand Down Expand Up @@ -218,7 +261,7 @@
# make label ascii compatible
$label =~ s/[^a-zA-Z0-9_-]//g ;
my $perf_value;
$perf_value = $json_response->{$key};
$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
Expand All @@ -234,26 +277,57 @@
$np->add_perfdata(
label => lc $label,
value => $perf_value,
);
);
}
}
}
}

sub process_wildcard{
my($key,$json_response) = @_;

if ($np->opts->verbose) { (print "DEBUG: handling wildcard on key ". $key. "\n"); }
my @parts;
my @result;
if ($key !~ /\*/) {
$Data::Dumper::Terse = 1;
$Data::Dumper::Indent = 0;
if ($np->opts->verbose) { (print "DEBUG: Now checking: ". $key. " against: ". Dumper($json_response)."\n")};
my $output_value = Dumper(eval('$json_response->'.$key));
$Data::Dumper::Terse = 0;
$Data::Dumper::Indent = 1;
return $output_value;
} else {
@parts = split(/->[\{\[]?\*[\}\]]?->/,$key,2);
my $part1 = $parts[0];
my $part2 = $parts[1];
if ($np->opts->verbose) { (print "DEBUG: processing first part before wildcard: ". $part1 . "\n"); }
my $c = eval('$json_response->'.$part1);
return if (! $c);
if ($np->opts->verbose) { (print "DEBUG: process_wildcard: Fount childs: ".Dumper($c)."\n")};
foreach my $v (values($c)){
my $r = process_wildcard($part2,$v);
push(@result,$r) if $r;
}
}
return @result;
}

# output some vars in message
if ($np->opts->outputvars) {
foreach my $key ($np->opts->outputvars eq '*' ? map { "{$_}"} sort keys %$json_response : split(',', $np->opts->outputvars)) {
# use last element of key as label
my $label = (split('->', $key))[-1];
# make label ascii compatible
# make label ascii compatible i.e. remove the { and }
$label =~ s/[^a-zA-Z0-9_-]//g;
my $output_value;
$output_value = $json_response->{$key};
## Handle case of wildcard in the middle of the tree: {data}->*->{description}
$output_value = join(", ",process_wildcard($key,$json_response));
push(@statusmsg, "$label: $output_value");
}
}

$np->nagios_exit(
return_code => $result,
message => join(', ', @statusmsg),
message => join('; ', @statusmsg),
);