prometheus-community / json_exporter

A prometheus exporter which scrapes remote JSON by JSONPath
Apache License 2.0
639 stars 197 forks source link

[FR] Extend JSONPath syntax to get object names #309

Open ivanov17 opened 5 months ago

ivanov17 commented 5 months ago

Hello community,

At the moment we don't have a way to get JSON object names using JSONPath syntax. But some programs send statistics as objects that contain other objects rather than arrays. For example, this is the NGINX Unit statistics output:

{
    "connections": {
        "accepted": 1067,
        "active": 13,
        "idle": 4,
        "closed": 1050
    },

    "requests": {
        "total": 1307
    },

    "applications": {
        "wp": {
            "processes": {
                "running": 14,
                "starting": 0,
                "idle": 4
            },

            "requests": {
                "active": 10
            }
        },
        "mw": {
            "processes": {
                "running": 15,
                "starting": 0,
                "idle": 3
            },
            "requests": {
                "active": 12
            }
        }
    }
}

In this case we need to iterate over the applications object and get the name for each application object to use it as the metric label.

It seems that this problem should be solved by the exporter, not the application itself, because we can't control the output of each API. See also the case with another API in #250.

There is a practice to extend the JSONPath syntax to get the object names, parent elements, etc. For example, to get the name of an object, a tilde (~) is typically used. This syntax is used by the widely used JSONPath-Plus JS library and by the yaml-jsonpath Go library created by VMWare.

Using this syntax we could get the metrics for applications running by NGINX Unit like this:

---
modules:
  default:
    metrics:
      - name: "unit_app"
        type: "object"
        valuetype: "gauge"
        path: "{ .applications.* }"
        labels:
          app: "{ @~ }"
        values:
          processes_running: "{ .processes.running }"
          processes_starting: "{ .processes.starting }"
          processes_idle: "{ .processes.idle }"
          requests_active: "{ .requests.active }"

I think we don't need to switch from the current library or send a syntax-extending patch to the upstream, we need to add it just for this exporter.

For now, anyone experiencing this issue will need to fork the project just to add this feature and maintain it themselves. Or this can also be solved by creating an exporter that uses JMESPath. But simply extending the existing syntax seems preferable.

silveraignacio commented 4 months ago

+1 to this!

raccoon4x commented 4 months ago

Yes, this is very useful and necessary!

askfongjojo commented 2 months ago

+1 - I have a similar use case