Search code examples
arraysjsonjolt

JOLT transform that mixes common register data with array


Trying to make this transformation without success. From this input json (obtained from prometheus API which may not be relevant):

{
  "status": "success",
  "data": {
    "resultType": "matrix",
    "result": [
      {
        "metric": {
          "__name__": "hrStorageDescr",
          "hrStorageDescr": "/",
          "hrStorageIndex": "31",
          "instance": "instance1",
          "job": "snmp_linux_storage"
        },
        "values": [ [ 1687748400, "1" ], [ 1687748460, "2" ] ]
      },
      {
        "metric": {
          "__name__": "hrStorageDescr",
          "hrStorageDescr": "/var",
          "hrStorageIndex": "7",
          "instance": "instance2",
          "job": "snmp_linux_storage"
        },
        "values": [ [ 1687748400, "1" ], [ 1687748460, "2" ] ]
      },
      {
        "metric": {
          "__name__": "hrStorageDescr",
          "hrStorageDescr": "/",
          "hrStorageIndex": "31",
          "instance": "instance3",
          "job": "snmp_linux_storage"
        },
        "values": [ [ 1687748400, "1" ], [ 1687748460, "2" ] ]
      }
    ]
  }
}

I'd like to transform to this output, associating common data from the metric record to each of the values of the values array, and output as an array of records:

[
  {
    "hrStorageDescr": "/",
    "hrStorageIndex": "31",
    "instance": "instance1",
    "job": "snmp_linux_storage",
    "timestamp": 1687748400,
    "value": "1"
  },
  {
    "hrStorageDescr": "/",
    "hrStorageIndex": "31",
    "instance": "instance1",
    "job": "snmp_linux_storage",
    "timestamp": 1687748460,
    "value": "2"
  },
  {
    "hrStorageDescr": "/var",
    "hrStorageIndex": "7",
    "instance": "instance2",
    "job": "snmp_linux_storage",
    "timestamp": 1687748400,
    "value": "1"
  },
  {
    "hrStorageDescr": "/var",
    "hrStorageIndex": "7",
    "instance": "instance2",
    "job": "snmp_linux_storage",
    "timestamp": 1687748460,
    "value": "2"
  },
  {
    "hrStorageDescr": "/",
    "hrStorageIndex": "31",
    "instance": "instance3",
    "job": "snmp_linux_storage",
    "timestamp": 1687748400,
    "value": "1"
  },
  {
    "hrStorageDescr": "/",
    "hrStorageIndex": "31",
    "instance": "instance3",
    "job": "snmp_linux_storage",
    "timestamp": 1687748460,
    "value": "2"
  }
]

Any ideas?

Thanks in advance


Solution

  • You can deep dive upto the innermost array("values"), and tile the identifiers as

    [
      {
        "operation": "shift",
        "spec": {
          "data": {
            "result": {
              "*": { // the level of the "result" array which is represented by &3s below
                "values": {
                  "*": { // the level of the "values" array which is represented by &1s below 
                    "@2,metric.hrStorageDescr": "&3.&1.hrStorageDescr",
                    "@2,metric.hrStorageIndex": "&3.&1.hrStorageIndex",
                    "@2,metric.instance": "&3.&1.instance",
                    "@2,metric.job": "&3.&1.job",
                    "0": "&3.&1.timestamp",
                    "1": "&3.&1.value"
                  }
                }
              }
            }
          }
        }
      },
      { // get rid of the object keys
        "operation": "shift",
        "spec": {
          "*": {
            "*": {
              "@": ""
            }
          }
        }
      }
    ]
    

    or you can even do more dynamically by without hardcoding the subelements of the "metric" object such as

    [
      {
        "operation": "shift",
        "spec": {
          "data": {
            "result": {
              "*": {
                "values": {
                  "*": {
                    "@2,metric": { "*": "&4[&2].&" },
                    "0": "&3[&1].timestamp",
                    "1": "&3[&1].value"
                  }
                }
              }
            }
          }
        }
      },
      { // get rid of the object keys
        "operation": "shift",
        "spec": {
          "*": {
            "*": {
              "@": ""
            }
          }
        }
      },
      { // get rid of the unwanted attribute
        "operation": "remove",
        "spec": {
          "*": {
            "__name__": ""
          }
        }
      }
    ]
    

    the demo on the site http://jolt-demo.appspot.com/ is

    enter image description here