The JSON Datasource executes requests against arbitrary backends and parses JSON response into Grafana dataframes.
To install this plugin using the grafana-cli
tool:
grafana-cli plugins install simpod-json-datasource
See here for more information.
When adding datasource add your API endpoint to the URL
field. That's where datasource will make requests to.
If you want to add custom headers, keep Access set to Server
.
An OpenAPI definition is at openapi.yaml. You can explore it using Swagger Editor.
To work with this datasource the backend needs to implement 4 endpoints:
GET /
with 200 status code response. Used for "Test connection" on the datasource config page.POST /metrics
to return available metrics.POST /metric-payload-options
to return a list of metric payload options.POST /query
to return panel data or annotations.
Those 3 endpoints are optional:
POST /variable
to return data for Variable of typeQuery
.POST /tag-keys
returning tag keys for ad hoc filters.POST /tag-values
returning tag values for ad hoc filters.
POST /metrics
In Panel > Queries
page. When configuring a query request using Builder
mode, it will send the request to obtain the available metrics. The request body will carry the current metric and payload. In the Builder
mode, if the reloadMetric
value in the load configuration is true, the api will also be triggered when the value is modified / switched.
Example request:
{}
Or.
{
"metric": "DescribeMetricList",
"payload":{
"cloud": "cf6591c5dad211eaa22100163e120f6e",
"namespace": "MySQL"
}
}
Example response:
[{
"label": "Describe metric list", // Optional. If the value is empty, use the value as the label
"value": "DescribeMetricList", // The value of the option.
"payloads": [{ // Configuration parameters of the payload.
"label": "Namespace", // The label of the payload. If the value is empty, use the name as the label.
"name": "namespace", // The name of the payload.
"type": "select", // If the value is select, the UI of the payload is a radio box. If the value is multi-select, the UI of the payload is a multi selection box; if the value is input, the UI of the payload is an input box; if the value is textarea, the UI of the payload is a multiline input box. The default is input.
"placeholder": "Please select namespace", // Input box / selection box prompt information.
"reloadMetric": true, // Whether to overload the metrics API after modifying the value of the payload.
"width": 10, // Set the input / selection box width to a multiple of 8px.
"options": [{ // If the payload type is select / multi-select, the list is the configuration of the option list.
"label": "acs_mongodb", // The label of the payload select option.
"value": "acs_mongodb", // The label of the payload value.
},{
"label": "acs_rds",
"value": "acs_rds",
}]
},{
"name": "metric",
"type": "select"
},{
"name": "instanceId",
"type": "select"
}]
},{
"value": "DescribeMetricLast",
"payloads": [{
"name": "namespace",
"type": "select"
},{
"name": "metric",
"type": "select"
},{
"name": "instanceId",
"type": "multi-select"
}]
}]
POST /metric-payload-options
When the payload type
is select
or multi-select
and the payload options
configuration is empty, expanding the drop-down menu will trigger this API. The request body will carry the current metric and payload.
Example Request:
{
"metric":"DescribeMetricList", // Current metric.
"payload": { // Current payload.
"namespace":"acs_ecs"
},
"name":"cms_metric" // The payload name of the option list needs to be obtained.
}
Example Response:
[{
"label": "CPUUtilization",
"value": "CPUUtilization"
},{
"label": "DiskReadIOPS",
"value": "DiskReadIOPS"
},{
"label": "memory_freeutilization",
"value": "memory_freeutilization"
}]
POST /query
Example request:
{
"panelId": 1,
"range": {
"from": "2016-10-31T06:33:44.866Z",
"to": "2016-10-31T12:33:44.866Z",
"raw": {
"from": "now-6h",
"to": "now"
}
},
"rangeRaw": {
"from": "now-6h",
"to": "now"
},
"interval": "30s",
"intervalMs": 30000,
"maxDataPoints": 550,
"targets": [
{ "target": "Packets", "refId": "A", "payload": { "additional": "optional json" } },
{ "target": "Errors", "refId": "B" }
],
"filters": [{
"key": "City",
"operator": "=",
"value": "Berlin"
}]
}
Response body can contain anything that is or can be converted to a Grafana DataFrame using this function. Returned data will be mapped to a DataFrame through that.
Example response (metric value as a float , unix timestamp in milliseconds):
[
{
"target":"pps in",
"datapoints":[
[622,1450754160000],
[365,1450754220000]
]
},
{
"target":"pps out",
"datapoints":[
[861,1450754160000],
[767,1450754220000]
]
},
{
"target":"errors out",
"datapoints":[
[861,1450754160000],
[767,1450754220000]
]
},
{
"target":"errors in",
"datapoints":[
[861,1450754160000],
[767,1450754220000]
]
}
]
[
{
"columns":[
{"text":"Time","type":"time"},
{"text":"Country","type":"string"},
{"text":"Number","type":"number"}
],
"rows":[
[1234567,"SE",123],
[1234567,"DE",231],
[1234567,"US",321]
],
"type":"table"
}
]
The relation between target
in request and response is 1:n. You can return multiple targets in response for one requested target
.
Sending additional data for each metric is supported via the Payload
input field that allows you to enter any JSON string.
For example, when { "additional": "optional json" }
is entered into Payload
input, it is attached to the target data under "payload"
key:
{ "target": "upper_50", "refId": "A", "payload": { "additional": "optional json" } }
You can also enter variables:
POST /variable
Example request body:
{
"payload":{"target":"systems"},
"range":{
"from":"2022-02-14T08:09:32.164Z",
"to":"2022-02-21T08:09:32.164Z",
"raw":{"from":"now-7d","to":"now"}
}
}
"payload"
is value from your input in Variable edit form.
Example response
[
{"__text":"Label 1", "__value":"Value1"},
{"__text":"Label 2", "__value":"Value2"},
{"__text":"Label 3", "__value":"Value3"}
]
DataFrame is also supported.
POST /tag-keys
Example request body
{ }
The tag keys api returns:
[
{"type":"string","text":"City"},
{"type":"string","text":"Country"}
]
POST /tag-values
Example request body
{"key": "City"}
The tag values api returns:
[
{"text": "Eins!"},
{"text": "Zwei"},
{"text": "Drei!"}
]