Ad Widget

Collapse

Custom LLD JSON Macros

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • MRedbourne
    Senior Member
    • Feb 2023
    • 103

    #1

    Custom LLD JSON Macros

    Hello! I'm back with more LLD questions. I'm quite close to getting this worked out, but I can't quite get the final step. I have an item in a custom Zabbix which pulls JSON data from a monitored server. This is done using a custom UserParameter statement, which calls the local application with the correct flags. It then gets pre-processed by JS to remove the first line. The returned data at the item level is formatted like this:

    Code:
    {
    "https://agentserviceapi.guestconfiguration.azure.com": {
    "hostname": "agentserviceapi.guestconfiguration.azure.com",
    "ipAddresses": [
    "20.125.173.160"
    ],
    "private": "false",
    "reachable": true,
    "proxyStatus": "not used",
    "tls": "TLS 1.3",
    "legacy": false,
    "useCase": "core",
    "error": "",
    "requiredForPrivateLinkScope": true,
    "privateLinkScopeWarnings": null,
    "privateLinkScopeErrors": null
    },
    "https://centralus-gas.guestconfiguration.azure.com": {
    "hostname": "centralus-gas.guestconfiguration.azure.com",
    "ipAddresses": [
    "172.202.65.10",
    "172.202.64.10",
    "2603:1030:13:200::10",
    "2603:1030:13:201::10"
    ],
    "private": "false",
    "reachable": true,
    "proxyStatus": "not used",
    "tls": "TLS 1.3",
    "legacy": false,
    "useCase": "core",
    "error": "",
    "requiredForPrivateLinkScope": true,
    "privateLinkScopeWarnings": null,
    "privateLinkScopeErrors": null
    }
    }
    The returned values are variable, so not every server's response will contain the same domains to check for. To solve this issue, I'm attempting to have Zabbix use discovery rules with LLD macros and item prototypes to dynamically create the items. My issue is, I can't seem to quote get the LLD macro correct.

    Discovery Rule
    Name: Discover Endpoints
    Type: Dependent Item
    Key: azcmagent.check.connectivity
    Master Item: [Template] Azure Arc Check (JSON/Master)
    LLD Macro: {#ENDPOINT} -> $.[*]

    Item Prototype (I've tried variations on the JSON path here)
    Name: {#ENDPOINT}: TLS Version
    Type: Dependent Item
    key: azcmagent.check.connectivity.tlsversion[{#ENDPOINT}]
    Type of Info: Text
    Master Item: [Template] Azure Arc Check (JSON/Master)
    Processing: JSONPath -> $.[{#ENDPOINT}].tls

    Click image for larger version  Name:	image.png Views:	0 Size:	18.4 KB ID:	498348


    If I manually set the macro value in the prototype to "https://agentserviceapi.guestconfiguration.azure.com" for example, I get the correct value of "TLS 1.3". However, if I just leave the item prototype as is, it doesn't process anything. Which makes me think something is wrong with the LLD macro

    Click image for larger version  Name:	image.png Views:	4 Size:	20.5 KB ID:	498344

    I've been writing the JSON parsers in JQ and then fiddling with it once I get to Zabbix. What I'm using the capture the "LLD" part in JQ is:
    • jq 'keys[]' response.json
    • jq keys | .[]' response.json
    Both of which return the correct values:
    Click image for larger version  Name:	image.png Views:	0 Size:	36.0 KB ID:	498347
    It doesn't work in Zabbix. I also tried $.[*] as the LLD macro, which also didn't work. Any ideas what I'm doing wrong?​

    Edit: Bad OpSec...
    Last edited by MRedbourne; 03-02-2025, 08:53.
  • kyus
    Senior Member
    • Feb 2024
    • 172

    #2
    For me it seems like the $.[*] path to extract a macro is the issue here...

    With the provided JSON this path will extract a lot of information, not only "https://agentserviceapi.guestconfiguration.azure.com"

    Maybe you could try something like:
    Code:
    $.*~

    Comment

    • MRedbourne
      Senior Member
      • Feb 2023
      • 103

      #3
      Originally posted by kyus
      For me it seems like the $.[*] path to extract a macro is the issue here...

      With the provided JSON this path will extract a lot of information, not only "https://agentserviceapi.guestconfiguration.azure.com"

      Maybe you could try something like:
      Code:
      $.*~
      I'd tend to agree with you that the LLD macro is the issue here. It's just tinkering with it enough until it works. The tilde ("~") is a good callout and something I missed when reading the JSONPath functionality docs./ Interestingly, I tried these 5 paths as well, none of which appear to have worked.

      Code:
      $.[*]~
      $.[]~
      $.*~
      $.~
      Perhaps a better question might be - we can test the full JSON path extraction when working with the final item as a pre-processor. Is there a method for us to test the LLD macro extraction that I don't know of?

      Comment

      • MRedbourne
        Senior Member
        • Feb 2023
        • 103

        #4
        To answer my own last question: This is testing the $.*~ JSON path, which appears to be correct. Doesn't appear to be generating any items though.

        Click image for larger version

Name:	image.png
Views:	301
Size:	20.2 KB
ID:	498462
        Item Prototype:
        Click image for larger version

Name:	image.png
Views:	288
Size:	18.5 KB
ID:	498463
        Item Prototype (with a member of the array?) - parses correctly. I did double check the item and rules. The discovery rule is enabled, as is the create and discover in the item prototype. Now I'm actually confused. All the pieces seem to be in place.
        Click image for larger version

Name:	image.png
Views:	295
Size:	24.5 KB
ID:	498464​​

        Comment

        • Brambo
          Senior Member
          • Jul 2023
          • 245

          #5
          Your example Json isn't an array which should start with square bracket []
          To work with LLD my experience is that this is needed.
          Try you jsonpath code with jsonpath.com and when you need a dubbel . for values the jsonpath in zabbix is single.
          That your Test Item work is a confirmation that {#ENDPOINT} isn't set with the expected value.

          BTW if your results comes back with "value" (the quotes) then use .first() and the end of your jsonpath.

          Comment

          • MRedbourne
            Senior Member
            • Feb 2023
            • 103

            #6

            Originally posted by Brambo
            Your example Json isn't an array which should start with square bracket []
            To work with LLD my experience is that this is needed.
            Try you jsonpath code with jsonpath.com and when you need a dubbel . for values the jsonpath in zabbix is single.
            That your Test Item work is a confirmation that {#ENDPOINT} isn't set with the expected value.

            BTW if your results comes back with "value" (the quotes) then use .first() and the end of your jsonpath.
            I'm not sure I'm following on the array part. If I put my JSON example into the jsonpath.com website it's returned as valid. If I set the parser to JSONPath+ and the extractor to
            Code:
            $.*~
            , it extracts the array correctly.

            Click image for larger version

Name:	image.png
Views:	294
Size:	85.5 KB
ID:	498506

            Comment

            • kyus
              Senior Member
              • Feb 2024
              • 172

              #7
              Just one thing to note: multiple times when I was working with LLD, I would get the json value that Zabbix receives and use it in a preprocessing step (JSONPath) to simulate what the LLD Macros were extracting. And sometimes, the path that would work correctly in the LLD Macro would return an error when testing in the preprocessing step.

              This could be an expected behaviour, I'm not sure, maybe this is happening in your LLD aswell

              Comment

              • cyber
                Senior Member
                Zabbix Certified SpecialistZabbix Certified Professional
                • Dec 2006
                • 4807

                #8

                I think jsonpath plus behaviour there is not working... I am struggling currently with same thing (logstash pipeline stats).

                Comment


                • MRedbourne
                  MRedbourne commented
                  Editing a comment
                  See my comment below. However, I've added a note to that feature/change request as it's what I'm looking for. Tagged the assignee as well, given the age of the request. THanks!
              • MRedbourne
                Senior Member
                • Feb 2023
                • 103

                #9
                Logstash I can help with potentially! We're calling the logstash API through the localhost listener (our servers are all remote, and we didn't want to expose the service to the internet, regardless of authentication or firewall controls.)

                These items are dynamically created as an example. Template supports multiple hosts being added.
                Click image for larger version

Name:	image.png
Views:	300
Size:	149.4 KB
ID:	498613

                JSON Template > Logstash TPL - Pastebin.com
                User Parameters:
                Code:
                UserParameter=logstashFLOW,curl -s -XGET 'localhost:9600/_node/stats/flow?pretty'
                UserParameter=logstashJVM,curl -s -XGET 'localhost:9600/_node/stats/jvm?pretty'
                UserParameter=logstashPROCESS,curl -s -XGET 'localhost:9600/_node/stats/process?pretty'
                UserParameter=logstashPIPELINE,curl -s -XGET 'localhost:9600/_node/stats/pipelines?pretty'
                UserParameter=logstashEVENT,curl -s -XGET 'localhost:9600/_node/stats/events?pretty'​

                Comment

                • cyber
                  Senior Member
                  Zabbix Certified SpecialistZabbix Certified Professional
                  • Dec 2006
                  • 4807

                  #10
                  Gettiing data out of logstash is easy, does not require even userparameters.. getting discoveries working, thats my issue.. But I have my own issues with jsonpath.. maybe there is not so big of an deal, I will take a look on your template, thank you for that
                  Code:
                  web.page.get["{HOST.CONN}:9600/_node/stats/pipelines"]
                  add "?pretty" if you want, but for processing it is not necessary. Replace {HOST.CONN} with localhost, if needed.

                  Comment

                  • Brambo
                    Senior Member
                    • Jul 2023
                    • 245

                    #11
                    Originally posted by MRedbourne


                    I'm not sure I'm following on the array part. If I put my JSON example into the jsonpath.com website it's returned as valid. If I set the parser to JSONPath+ and the extractor to
                    Code:
                    $.*~
                    , it extracts the array correctly.

                    Click image for larger version  Name:	image.png Views:	24 Size:	85.5 KB ID:	498506
                    Maybe check if this data you have on the right side is being processed the way you want. And then use preprocessing to make it LLD ready.
                    Click image for larger version  Name:	image.png Views:	0 Size:	31.1 KB ID:	498650
                    To give an idea:
                    Explanation. Step 1 creates a list like your picture on the right side. (my source data has an name item on several sublevels deep)
                    step 2 is to offload unnecessary LLD discovery action (when a name changes it will be run directly (interval of getting the list is 30s)
                    step 3 to 5 is building the array with a named path to be used in the LLD rule.

                    PS this item is depending on the original data item.
                    The LLD rule is depending on this item.
                    Item prototypes depending on original data item.

                    Maybe this setup can help you out with the unnamed items toward LLD rule

                    Comment

                    • MRedbourne
                      Senior Member
                      • Feb 2023
                      • 103

                      #12
                      I have this working now! I sort of did what Brambo suggested. I did a 3-stage JS pre-processor which did a couple things:
                      1. Remove the top line of the returned object. Azure Arc injects a string ("INFO Testing connectivity to endpoints that are needed to connect to Azure... This might take a few minutes.") which obviously isn't JSON compatible.
                      2. Replace the 'new' first line and last line of the JSON object ("{", "}" respectively) with "[" and "]" respectively.
                      3. Replaced any line containing "https://" with the character "{".
                      The result was a text that looked like this (Pre-processor - Pastebin.com) to this (Post-processing - Pastebin.com​). THe post-processing is LLD compatible. The LLD macro was set to {#ENDPOINT} -> $.hostname, which returns a set of objects. From there, it's normal JSON parsing (JSONPath => $..[?(@.hostname == "{#ENDPOINT}")].legacy.first()) with a little bit of trimming: Trim => []"

                      JS Scripts to do the processing:
                      Code:
                      var lines = value.split('\n');
                      lines.splice(0,1);
                      var newtext = lines.join('\n');
                      return newtext​
                      Code:
                      var lines = value.split('\n');
                      lines[0] = '[';  // First line replaced with '['
                      lines[lines.length - 1] = ']';  // Last line replaced with ']'
                      var transformedText = lines.join('\n');
                      return transformedText​
                      Code:
                      return value.replace(/^.*https.*$/gm, '{');
                      Hope this helps someone.

                      Comment

                      Working...