Ad Widget

Collapse

Arithmetic Calculation in a JSONPath based on LLDMACRO

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • high-t
    Member
    • Dec 2014
    • 68

    #1

    Arithmetic Calculation in a JSONPath based on LLDMACRO

    Hi.

    I have a discovery rule that pulls out a series of numbers.
    The corresponding item prototype needs to pull data from an array, based on the data from the discovery rule. However the data pulled by the discovery rule is 1...end, and the corresponding array location is 0...end-1.
    So I need to be able to make the adjustments when configuring the Item Prototype.

    I tried using the following JSONPath:
    Code:
    $.body.data[?({#COMPONENT_ID}-1)].status
    But when testing it, I get the following result:

    cannot extract value from json by path "$.body.data[?(1-1)].status": no data matches the specified path
    This suggests to me that the calculation is no performed, but rather the system looks for the "1-1" string, hence the JSONPath query fails.

    Any ideas will be highly appreciated!
    Thank you in advance

    Amit.
  • vso
    Zabbix developer
    • Aug 2016
    • 190

    #2
    Could you please be so kind and also provide the data that you are working with ? It would speed up investigation, also why is it expected to work ? Would something like this do the trick ?
    $.body.data[({#COMPONENT_ID}-1)].status

    Comment

    • high-t
      Member
      • Dec 2014
      • 68

      #3
      Hi vso , and thank you for the reply.

      Unfortunately, the suggested formula didn't work. See screenshot here below:

      Click image for larger version

Name:	screenshot.png
Views:	1591
Size:	45.0 KB
ID:	395405

      The JSON document I'm trying to query is:

      Code:
      {
        "body": {
          "meta": {
            "pagination": {
              "total": 4,
              "count": 4,
              "per_page": 20,
              "current_page": 1,
              "total_pages": 1,
              "links": {
                "next_page": null,
                "previous_page": null
              }
            }
          },
          "data": [
            {
              "id": 1,
              "name": "Zabbix Server",
              "description": "",
              "link": "",
              "status": 1,
              "order": 0,
              "group_id": 1,
              "enabled": true,
              "created_at": "2020-02-08 22:01:11",
              "updated_at": "2020-02-11 03:44:02",
              "deleted_at": null,
              "status_name": "Operational",
              "tags": {
                "": ""
              }
            },
            {
              "id": 2,
              "name": "Zabbix DB",
              "description": "",
              "link": "",
              "status": 1,
              "order": 0,
              "group_id": 1,
              "enabled": true,
              "created_at": "2020-02-08 22:01:59",
              "updated_at": "2020-02-11 03:06:32",
              "deleted_at": null,
              "status_name": "Operational",
              "tags": {
                "": ""
              }
            },
            {
              "id": 3,
              "name": "Zabbix Website",
              "description": "",
              "link": "",
              "status": 1,
              "order": 0,
              "group_id": 1,
              "enabled": true,
              "created_at": "2020-02-08 22:02:32",
              "updated_at": "2020-02-11 03:37:32",
              "deleted_at": null,
              "status_name": "Operational",
              "tags": {
                "": ""
              }
            },
            {
              "id": 4,
              "name": "Alerts Gateway",
              "description": "",
              "link": "",
              "status": 1,
              "order": 0,
              "group_id": 1,
              "enabled": true,
              "created_at": "2020-02-08 22:03:30",
              "updated_at": "2020-02-11 03:37:56",
              "deleted_at": null,
              "status_name": "Operational",
              "tags": {
                "": ""
              }
            }
          ]
        }
      }

      Thank you for your help. Appreciated!

      Comment

      • vso
        Zabbix developer
        • Aug 2016
        • 190

        #4
        Is it an option to use this data as discovery item with preprocessing $.body.data
        Then you get array:
        Code:
        [      {         "id":1,
              "name":"Zabbix Server",
              "description":"",
              "link":"",
              "status":1,
              "order":0,
              "group_id":1,
              "enabled":true,
              "created_at":"2020-02-08 22:01:11",
              "updated_at":"2020-02-11 03:44:02",
              "deleted_at":null,
              "status_name":"Operational",
              "tags":{            "":""
        
         }
        
         },
           {         "id":2,
              "name":"Zabbix DB",
              "description":"",
              "link":"",
              "status":1,
              "order":0,
              "group_id":1,
              "enabled":true,
              "created_at":"2020-02-08 22:01:59",
              "updated_at":"2020-02-11 03:06:32",
              "deleted_at":null,
              "status_name":"Operational",
              "tags":{            "":""
        
         }
        
         },
           {         "id":3,
              "name":"Zabbix Website",
              "description":"",
              "link":"",
              "status":1,
              "order":0,
              "group_id":1,
              "enabled":true,
              "created_at":"2020-02-08 22:02:32",
              "updated_at":"2020-02-11 03:37:32",
              "deleted_at":null,
              "status_name":"Operational",
              "tags":{            "":""
        
         }
        
         },
           {         "id":4,
              "name":"Alerts Gateway",
              "description":"",
              "link":"",
              "status":1,
              "order":0,
              "group_id":1,
              "enabled":true,
              "created_at":"2020-02-08 22:03:30",
              "updated_at":"2020-02-11 03:37:56",
              "deleted_at":null,
              "status_name":"Operational",
              "tags":{            "":""
        
         }
        
         }
         ]
        Then use LLD macros {#COMPONENT_ID} -> $.id

        Now {#COMPONENT_ID} will be equal to all ids

        If it's not an option then the last resort would be to use javascript preprocessing step for LLD that would parse JSON and change values. Unfortunately there is no functionality in jsonpath to do operations on name, feature request can be made for such functionality but I am not sure if it's something that is done by any implementation of jsonpath.
        Last edited by vso; 12-02-2020, 12:18.

        Comment

        • high-t
          Member
          • Dec 2014
          • 68

          #5
          This is exactly what I'm practicing: I have a discovery rule where I pull this JSON, then preprocessing it and assigning the LLD Macros:

          Click image for larger version

Name:	screenshot.png
Views:	1480
Size:	9.7 KB
ID:	395416




          Click image for larger version

Name:	screenshot.png
Views:	1551
Size:	9.3 KB
ID:	395415

          This works just fine. No problem in the discovery rule.

          The problem is with the item prototype: Once my components are discovered, I then wish to query each component for its status (hence create an item per discovered component). However, the component array location is shifted from the it's id.
          So,for instance, to query on status of the component which its ID in the JSON document is "1", I need to run
          Code:
          https://<url>/component/0
          . Consequently, I need to subtract 1 from {#COMPONENT_ID}.... Hopefully that makes sense...

          Any ideas?

          Comment

          • vso
            Zabbix developer
            • Aug 2016
            • 190

            #6
            Could try LLD preprocessing with following javascript:
            Code:
            obj = JSON.parse(value);
            
            for (var i = 0; i < Object.keys(obj).length; i++) {
                obj[i].id-=1;
            }
            
            return JSON.stringify(obj);
            expected input value:
            Code:
             [
                  {
                    "id": 1,
                    "name": "Zabbix Server",
                    "description": "",
                    "link": "",
                    "status": 1,
                    "order": 0,
                    "group_id": 1,
                    "enabled": true,
                    "created_at": "2020-02-08 22:01:11",
                    "updated_at": "2020-02-11 03:44:02",
                    "deleted_at": null,
                    "status_name": "Operational",
                    "tags": {
                      "": ""
                    }
                  },
                  {
                    "id": 2,
                    "name": "Zabbix DB",
                    "description": "",
                    "link": "",
                    "status": 1,
                    "order": 0,
                    "group_id": 1,
                    "enabled": true,
                    "created_at": "2020-02-08 22:01:59",
                    "updated_at": "2020-02-11 03:06:32",
                    "deleted_at": null,
                    "status_name": "Operational",
                    "tags": {
                      "": ""
                    }
                  },
                  {
                    "id": 3,
                    "name": "Zabbix Website",
                    "description": "",
                    "link": "",
                    "status": 1,
                    "order": 0,
                    "group_id": 1,
                    "enabled": true,
                    "created_at": "2020-02-08 22:02:32",
                    "updated_at": "2020-02-11 03:37:32",
                    "deleted_at": null,
                    "status_name": "Operational",
                    "tags": {
                      "": ""
                    }
                  },
                  {
                    "id": 4,
                    "name": "Alerts Gateway",
                    "description": "",
                    "link": "",
                    "status": 1,
                    "order": 0,
                    "group_id": 1,
                    "enabled": true,
                    "created_at": "2020-02-08 22:03:30",
                    "updated_at": "2020-02-11 03:37:56",
                    "deleted_at": null,
                    "status_name": "Operational",
                    "tags": {
                      "": ""
                    }
                  }
                ]
            output:
            Code:
            [{
                "id": 0,
                "name": "Zabbix Server",
                "description": "",
                "link": "",
                "status": 1,
                "order": 0,
                "group_id": 1,
                "enabled": true,
                "created_at": "2020-02-08 22:01:11",
                "updated_at": "2020-02-11 03:44:02",
                "deleted_at": null,
                "status_name": "Operational",
                "tags": {
                    "": ""
                }
            }, {
                "id": 1,
                "name": "Zabbix DB",
                "description": "",
                "link": "",
                "status": 1,
                "order": 0,
                "group_id": 1,
                "enabled": true,
                "created_at": "2020-02-08 22:01:59",
                "updated_at": "2020-02-11 03:06:32",
                "deleted_at": null,
                "status_name": "Operational",
                "tags": {
                    "": ""
                }
            }, {
                "id": 2,
                "name": "Zabbix Website",
                "description": "",
                "link": "",
                "status": 1,
                "order": 0,
                "group_id": 1,
                "enabled": true,
                "created_at": "2020-02-08 22:02:32",
                "updated_at": "2020-02-11 03:37:32",
                "deleted_at": null,
                "status_name": "Operational",
                "tags": {
                    "": ""
                }
            }, {
                "id": 3,
                "name": "Alerts Gateway",
                "description": "",
                "link": "",
                "status": 1,
                "order": 0,
                "group_id": 1,
                "enabled": true,
                "created_at": "2020-02-08 22:03:30",
                "updated_at": "2020-02-11 03:37:56",
                "deleted_at": null,
                "status_name": "Operational",
                "tags": {
                    "": ""
                }
            }]

            Comment

            • high-t
              Member
              • Dec 2014
              • 68

              #7
              OK. That worked!
              Your javascript suggestion is a game changer!

              I was actually able to take this a step further:
              • Created an HTTP Agent type Item, to bring the components list JSON Document.
              • Created a Discovery Rule of type Dependent Item (depending on the above mentioned item).
                • Preprocessing the Discovery Rule (your code included here).

                  Click image for larger version  Name:	prepro.png Views:	0 Size:	5.7 KB ID:	395432
                • Use the JSON returned from the code to assign the LLD Macros.

                  Click image for larger version

Name:	lld.png
Views:	1447
Size:	5.4 KB
ID:	395434
              • Created a Item Prototype of type Dependent Item (depending on the same item as the discovery rule).
                • Preprocessing the item to bring the Status value (for each of the discovered components).

                  Click image for larger version  Name:	item.png Views:	0 Size:	4.2 KB ID:	395433
              The reult

              Click image for larger version  Name:	latest_data.png Views:	0 Size:	15.0 KB ID:	395431

              The rationale for this
              Previously, I used a rather strait forward approach: A discovery rule and Prototype Items, all of type HTTP Agent. This approach resulted N+1 calls to the API agent (N being the number of discovered components). Having plans to significantly increase the number of components, I knew this would most probably bring the web server to a degraded performance.

              By implementing this query architecture, I was able to actually make just a single HTTP call to the API engine, to get the item data. An important offload.

              Click image for larger version  Name:	graph.png Views:	0 Size:	65.1 KB ID:	395430

              Thank you, @vso for the awesome support. You have been extremely helpful. I highly appreciate it!
              Last edited by high-t; 12-02-2020, 16:57.

              Comment

              • vso
                Zabbix developer
                • Aug 2016
                • 190

                #8
                If you can use same data as source then there is no need for javascript preprocessing, simply use
                Code:
                body.data[?(@.id=='{#COMPONENT_ARRAY_ID}')].status
                in item prototype

                Comment

                • high-t
                  Member
                  • Dec 2014
                  • 68

                  #9
                  Hmm... I'm not sure I fully understand your point..
                  Currently, there is only one step in the item prototype preprocessing:

                  Click image for larger version

Name:	prepro.png
Views:	1465
Size:	10.4 KB
ID:	395442




                  The Javascript code runs as a preprocessing of the Discovery Rule:

                  Click image for larger version

Name:	item.png
Views:	1495
Size:	12.6 KB
ID:	395443


                  What am I missing here...??

                  Comment

                  • vso
                    Zabbix developer
                    • Aug 2016
                    • 190

                    #10
                    This step should be replaced to:
                    body.data[?(@.id=='{#COMPONENT_ARRAY_ID}')].status And javascript preprocessing removed

                    Comment

                    • high-t
                      Member
                      • Dec 2014
                      • 68

                      #11
                      But, the reason for the javascript is to shift the id values by minus 1.
                      If the javascript is removed, what will make that adjustment?

                      Comment

                      • vso
                        Zabbix developer
                        • Aug 2016
                        • 190

                        #12
                        It will search by actual id value where id equals 1 for example

                        Comment

                        • high-t
                          Member
                          • Dec 2014
                          • 68

                          #13
                          Well, it works, but return the value with the brackets.
                          I know I can left and right trim the value, but if that is the case, isn't that as expensive as running the javascript code?


                          Click image for larger version

Name:	screenshot.png
Views:	1461
Size:	15.4 KB
ID:	395451

                          Comment

                          • vso
                            Zabbix developer
                            • Aug 2016
                            • 190

                            #14
                            You can add .first() function to jsonpath, in this case no trimming will be required

                            Comment

                            • high-t
                              Member
                              • Dec 2014
                              • 68

                              #15
                              Works like a charm

                              Click image for larger version  Name:	item.png Views:	0 Size:	11.4 KB ID:	395461


                              Click image for larger version  Name:	latest_data.png Views:	0 Size:	15.3 KB ID:	395462


                              So this syntax is new to me:

                              Code:
                              $.body.data[?(@.id=='{#COMPONENT_ARRAY_ID}')].status.first()
                              Does this means: For each item in the array "data", where the value of "id" equals the value of the LLDMACRO , return the first value of "status"?
                              Man.. this thing is complicated...
                              Attached Files
                              Last edited by high-t; 12-02-2020, 20:55.

                              Comment

                              Working...