Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unable to output perfdata from traversed object #23

Open
lesinigo opened this issue Aug 24, 2016 · 9 comments
Open

unable to output perfdata from traversed object #23

lesinigo opened this issue Aug 24, 2016 · 9 comments

Comments

@lesinigo
Copy link

lesinigo commented Aug 24, 2016

I am checking a value nested in an array (eg. the same thing that was broken and later fixed in issue #21 ) and the checking itself, complete with thresholds logic, seems to be working ok:

./check_json.pl -u http://user:[email protected]:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=foobar -a '{value}->{ConsumerCount}' -w 2: -c 2:
Check JSON status API OK

But I'm not able to get the same value in outputvars, and the scripts returns this warning:

./check_json.pl -u http://user:[email protected]:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=foobar -a '{value}->{ConsumerCount}' -w 2: -c 2: -o '{value}->{ConsumerCount}'
Use of uninitialized value $output_value in concatenation (.) or string at ./check_json.pl line 252.
Check JSON status API OK - ConsumerCount: 

And I cannot get the values in perfdata too, but this time without any warning:

./check_json.pl -T text/plain -u http://user:[email protected]:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=foobar -a '{value}->{ConsumerCount}' -w 1: -c 1: -p '{value}->{ConsumerCount}'
Check JSON status API OK
@ClouDevops101
Copy link

Got the same issues :

./check_json.pl --url "http://api.aladhan.com/timingsByCity?city=Dubai&country=AE&method=2" --attribute '{code}->{value}' --warning :400 --critical :400  --perfvars '{code}->{value}'

Check JSON status API UNKNOWN - No value received

@khba
Copy link

khba commented Nov 28, 2016

Got the same issue too.

@waoki
Copy link

waoki commented Jan 31, 2017

This happens because $json_response contains the structured JSON response, but the script tries to pull data out of it using the raw user-provided key. For example, it tries to look up $json_response->{'{foo}->{bar}'} instead of $json_response->{'foo'}->{'bar'}.

I've created a patch that partially fixes it, but I'm holding off on actually making a pull request until I have '-o *' support working.

@senorsmile
Copy link

I created a patch this morning and submitted a PR, without realizing this conversation had taken place. I haven't tested the patch with "*" though.

@waoki
Copy link

waoki commented May 12, 2017

I never got around implementing a way for -o to pull individual things out of arrays because I fixed it as much as I needed (to pull individual keys out of deeply-nested data from PaperCut), but feel free to take what you need from https://github.com/waoki/check_json. I can create a PR if that would be helpful.

@kwisatz
Copy link

kwisatz commented Oct 6, 2017

Neither of those two solutions work for me. They don't seem to be working with arrays. The only way I made it work was to change it to this:

220         my $perf_value;
221         my $perf_value_str = '$perf_value = $json_response->'.$key;
222         eval $perf_value_str;
223         print $perf_value;

E.g if you have something like:

"results": [
        {
            "status": {
                "api": {
                    "http": {
                        "clients": 1.0
                    },
            }
        },
        {
            "status": {
                "another_key": 2,
                "andsoon": 1.345
         }
]

Then $ptr->{$i}, i.e. $json_response->results[0] will result in an empty string.
Is that what @waoki was referring to in their commit message here waoki@df61837 ?

The fun part is that this works for this prefvalue: -p '{results}[0]->{status}->{api}->{http}->{clients} but not for e.g. -p {results}[1]->{status}->{num_hosts_up}.

@kwisatz
Copy link

kwisatz commented Oct 7, 2017

I also think this behavior is weird, but maybe it's just me being tired or not understanding how perl works at all. I tried adding all perfdata keys to attributes, which – for reasons I don't understand – seems to work, but then:

~# /usr/lib/nagios/plugins/check_json -u https://localhost:6670/v1/status -w :5 -c :10 \
--attributes '{results}[0]->{status}->{api}->{http}->{clients},{results}[1]->{status}->{max_latency}' \
--ignoressl -p '{results}[0]->{status}->{api}->{http}->{clients},{results}[1]->{status}->{max_latency}' \
-e 1
Check JSON status API CRITICAL - Expected value (1) not found. Actual: 0.00407576560974121

~# /usr/lib/nagios/plugins/check_json -u https://localhost:6670/v1/status -w :5 -c :10 \
--attributes '{results}[0]->{status}->{api}->{http}->{clients},{results}[1]->{status}->{max_latency}' \
--ignoressl -p '{results}[0]->{status}->{api}->{http}->{clients},{results}[1]->{status}->{max_latency}' \
-e 1,
Check JSON status API CRITICAL - Expected value (1,) not found. Actual: 1

Why does the actual value change when I change the value of e ?

@waoki
Copy link

waoki commented Oct 16, 2017

It's been a while since I looked at it, but yes, that's the kind of structure I was thinking about.

It looks like I started working on it, but then had to set it aside and never came back to it. I have these uncommitted changes sitting locally which look like initial work on the problem:

diff --git a/check_json.pl b/check_json.pl
index 39ffecf..b37a944 100755
--- a/check_json.pl
+++ b/check_json.pl
@@ -256,7 +256,8 @@ if ($np->opts->perfvars) {
 
 # recurse_json($json_data, \&callback);
 # recurse_json($json_data, \&callback, $path);
-# Invokes &callback for every terminal node in $json_data.
+# Invokes &callback for every terminal node in $json_data, unless it
+# is an array of scalars. This is needed for pretty-printing.
 # &callback is passed the name and the value of the leaf, i.e.
 #    callback($label, $value)
 # If $path is defined, recurse_json prepends it to $label. When recursing,
@@ -273,6 +274,18 @@ sub recurse_json {
     } elsif (ref($ptr) eq 'ARRAY') {
        @k = keys(@$ptr);
     }
+
+    # If it's an array, do we need to recurse? Unfortunately, we must check
+    # whole structure first so we can make the right decision.
+    if (ref($ptr) eq 'ARRAY') {
+       foreach my $i (@k) {
+          if (ref($ptr->[$i])) {
+            &callback($path, $ptr);
+            return;
+          }
+       }
+    }
+
     foreach my $i (@k) {
        my $p = $path;
        if (defined($p) && $p ne '') {
@@ -342,8 +355,7 @@ if ($np->opts->outputvars) {
            }
         }
 
-        # depending on desired behavior, this could just be ref($ptr)
-        if (ref($ptr) eq 'HASH') {
+        if (ref($ptr)) {
            recurse_json($ptr, sub {
               push(@statusmsg, format_output(@_));
            }, '');

@ErrafayM
Copy link

I have same issue, anyone got the right fix?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants