0

I'm currently working on a script to update Grafana dashboards through the API, and I keep encountering issues when sending my JSON payload. Each time I make the request, I receive a <response 400> error, which seems to suggest a problem with the JSON formatting. I've taken care to ensure that my JSON payload follows the template provided in the API documentation, yet the problem persists. Could someone assist me in identifying what might be causing this issue? I'm relatively new to updating Grafana dashboards via API and not entirely sure what might be missing or incorrect in my approach.

I suspect that the issue might be related to how I've structured my JSON payload, but I'm not entirely sure what might be causing the problem, as I'm new to this process of updating Grafana dashboards programmatically. Any insights or suggestions would be greatly appreciated.

Here's the JSON payload I'm attempting to send: And here the function I'm using to make the POST request to Grafana:

{
    "dashboard": {
        "id": 765,
        "panels": [
            {
                "alert": {
                    "alertRuleTags": {},
                    "conditions": [
                        {
                            "evaluator": {
                                "params": [
                                    70,
                                    5
                                ],
                                "type": "within_range"
                            },
                            "operator": {
                                "type": "and"
                            },
                            "query": {
                                "params": [
                                    "B",
                                    "24h",
                                    "now-12h"
                                ]
                            },
                            "reducer": {
                                "params": [],
                                "type": "last"
                            },
                            "type": "query"
                        }
                    ],
                    "executionErrorState": "keep_state",
                    "for": "5m",
                    "frequency": "1m",
                    "handler": 1,
                    "message": "",
                    "name": "XX",
                    "noDataState": "keep_state",
                    "notifications": []
                },
                "aliasColors": {},
                "bars": false,
                "dashLength": 10,
                "dashes": false,
                "datasource": "1",
                "fieldConfig": {
                    "defaults": {
                        "custom": {},
                        "links": []
                    },
                    "overrides": []
                },
                "fill": 1,
                "fillGradient": 0,
                "gridPos": {
                    "h": 9,
                    "w": 6,
                    "x": 0,
                    "y": 0
                },
                "hiddenSeries": false,
                "id": 4,
                "legend": {
                    "avg": false,
                    "current": false,
                    "max": false,
                    "min": false,
                    "show": true,
                    "total": false,
                    "values": false
                },
                "lines": true,
                "linewidth": 1,
                "nullPointMode": "null",
                "options": {
                    "alertThreshold": true
                },
                "percentage": false,
                "pluginVersion": "7.3.5",
                "pointradius": 2,
                "points": false,
                "renderer": "flot",
                "seriesOverrides": [],
                "spaceLength": 10,
                "stack": false,
                "steppedLine": false,
                "targets": [
                    {
                        "alias": "",
                        "groupBy": [
                            {
                                "params": [
                                    "1s"
                                ],
                                "type": "time"
                            }
                        ],
                        "hide": false,
                        "measurement": "",
                        "orderByTime": "ASC",
                        "policy": "default",
                        "refId": "A",
                        "resultFormat": "time_series",
                        "select": [
                            [
                                {
                                    "params": [
                                        ""
                                    ],
                                    "type": "field"
                                },
                                {
                                    "params": [],
                                    "type": "last"
                                }
                            ]
                        ],
                        "tags": [
                            {
                                "key": "",
                                "operator": "=",
                                "value": ""
                            },
                            {
                                "condition": "AND",
                                "key": "source",
                                "operator": "=",
                                "value": "file"
                            }
                        ]
                    },
                    {
                        "alias": "",
                        "groupBy": [
                            {
                                "params": [
                                    "1s"
                                ],
                                "type": "time"
                            }
                        ],
                        "hide": false,
                        "measurement": "telemetry",
                        "orderByTime": "ASC",
                        "policy": "default",
                        "refId": "B",
                        "resultFormat": "time_series",
                        "select": [
                            [
                                {
                                    "params": [
                                        ""
                                    ],
                                    "type": "field"
                                },
                                {
                                    "params": [],
                                    "type": "last"
                                }
                            ]
                        ],
                        "tags": [
                            {
                                "key": "",
                                "operator": "=",
                                "value": ""
                            },
                            {
                                "condition": "AND",
                                "key": "source",
                                "operator": "=",
                                "value": "file"
                            }
                        ]
                    }
                ],
                "thresholds": [
                    {
                        "colorMode": "critical",
                        "fill": true,
                        "line": true,
                        "op": "gt",
                        "value": 3,
                        "yaxis": "left"
                    },
                    {
                        "colorMode": "critical",
                        "fill": true,
                        "line": true,
                        "op": "lt",
                        "value": 5,
                        "yaxis": "left"
                    }
                ],
                "timeFrom": null,
                "timeRegions": [],
                "timeShift": null,
                "title": "",
                "tooltip": {
                    "shared": true,
                    "sort": 0,
                    "value_type": "individual"
                },
                "type": "graph",
                "xaxis": {
                    "buckets": null,
                    "mode": "time",
                    "name": null,
                    "show": true,
                    "values": []
                },
                "yaxes": [
                    {
                        "format": "volt",
                        "label": null,
                        "logBase": 1,
                        "max": "30",
                        "min": "0",
                        "show": true
                    },
                    {
                        "format": "short",
                        "label": null,
                        "logBase": 1,
                        "max": null,
                        "min": null,
                        "show": true
                    }
                ],
                "yaxis": {
                    "align": false,
                    "alignLevel": null
                }
            }
        ],
        "uid": "o-XW-FgSk",
        "version": 12
    },
    "overwrite": true,
    "message": "Testing"
}

And here the function I'm using to make the POST request to Grafana:

def post_request_grafana(endpoint, data):
    logging.basicConfig(level=logging.INFO)
    auth_token = "redacted"
    headers = {
        "Authorization": f"Bearer {auth_token}",
        "Content-Type": "application/json",
        "Accept": "application/json"
    }
    try:
        r = requests.post(endpoint, headers=headers, json=data)
        r.raise_for_status()
        
        logging.info(f"Successfully posted data to {endpoint}.")
        return r.json() 
    except requests.exceptions.RequestException as err:
        logging.error(f"Error posting to Grafana: {err}")
}

  • I’m posting to the api/dashboards/db endpoint – Caspernoah23426 Aug 28 '23 at 15:55
  • Your code without changes but with [this input](https://grafana.com/docs/grafana/latest/developers/http_api/create-api-tokens-for-org/#how-to-add-a-dashboard) (adjusted it it be correct python dictionary: `null` -> `'null'`, `false` -> `False`) succeeded. – markalex Aug 28 '23 at 19:44
  • Are you passing json from your question as a string or as a dictionary? Also, what error is shown in grafana's log? – markalex Aug 28 '23 at 19:44
  • so here is the log message: t=2023-08-28T17:06:26+0000 lvl=info msg="Request Completed" logger=context userId=0 orgId=1 uname= method=POST path=/api/dashboards/db status=400 remote_addr=10.752.4.251 time_ms=14 size=175 referer= – Caspernoah23426 Aug 28 '23 at 20:18
  • And the one before it with `level=error msg="bad request data"`? – markalex Aug 28 '23 at 20:28
  • So, addressing your earlier point, there are cases where data keys like 'null' and 'false' are enclosed in quotes. This is because they appeared that way in the original JSON payload. Additionally, there are instances where I added quotes as placeholders for security purposes. However, this shouldn't be the issue. – Caspernoah23426 Aug 28 '23 at 20:34
  • Oh, that one is from my script. I scripted it to output things that way. However, what I just posted is how it's being logged by the server. – Caspernoah23426 Aug 28 '23 at 20:37
  • Is this what you mean: ERROR:root:Error posting to Grafana: 400 Client Error: Bad Request for url: .../api/dashboards/db – Caspernoah23426 Aug 28 '23 at 20:39
  • No, what I meant is an error message from grafana log, not your application. – markalex Aug 28 '23 at 21:04
  • Oh I see! I don't see that log. I don't have any log with level=error they are all info – Caspernoah23426 Aug 28 '23 at 21:45
  • What type is `data`, that you are passing into your function? Is it a string or dictionary? It would be better if you include that data into your fully working [MCVE], so anybody can copy what you are doing without any assumptions. (Also, add comments what you changed for privacy reasons). – markalex Aug 29 '23 at 16:29
  • Also please look where you changed logging configuration of Grafana, and at least temporarily re-enable it fully. Error logs should be visible by default, and ease debugging of such problems significantly. – markalex Aug 29 '23 at 16:30
  • I updated the Json payload to show the full thing. the data i am passing should be a dictionary – Caspernoah23426 Aug 30 '23 at 22:50
  • If by error log you mean the stack trace then for some reason I can't see that either seems like grafana is not sending us those – Caspernoah23426 Aug 30 '23 at 22:55
  • If you are passing data as dictionary, you should use `data=` instead of `json=` – markalex Aug 31 '23 at 05:08
  • It worked thank you very much!! – Caspernoah23426 Aug 31 '23 at 17:44

0 Answers0