Skip to content

Instantly share code, notes, and snippets.

@svet-b
Last active December 27, 2022 09:01
Show Gist options
  • Save svet-b/772f88b92eee88db7da5cefe8d3d4edb to your computer and use it in GitHub Desktop.
Save svet-b/772f88b92eee88db7da5cefe8d3d4edb to your computer and use it in GitHub Desktop.
PDF export of Grafana dashboard via snapshot

Get PDF export of Grafana dashboard

Note

As currently described, this approach does not work. The reason for that is that creating a snapshot via the API does not actually populate any data, as described in e.g. https://community.grafana.com/t/snapshot-using-http-api-does-nothing/. An alternative approach which does work described in https://gist.github.com/svet-b/1ad0656cd3ce0e1a633e16eb20f66425.

Prerequisites

Packages:

  • The jq JSON processing command line tool, which is available for most distributions (https://stedolan.github.io/jq/, sudo apt install jq)
  • NodeJS, and the puppeteer package (npm install puppeteer), which is used to run headless Chrome

Scripts:

  • The pdf.js file attached here, which carries out the PDF conversion

Also, create Grafana API key from web UI (http://docs.grafana.org/http_api/auth/ has some outdated instructions but the idea holds). Save it in an environment variable, along with your Grafana instance URL

export APIKEY=eyJrIjoiMFdmMnA3YlRZTFF5bktqUmhRRk9nUzBISEo0dkZMNW0iLCJuIjoicGRmIiwiaWQiOjF9
export GURL=http://localhost:3000

Process

First we need to take a snapshot of the dashboard to be exported. We can do this via the API, per http://docs.grafana.org/http_api/snapshot/, but in order to request this we actually need the full dashboard JSON. This can be obtained via another API call, based on the dashboard ID - here saved as dashboard.json:

export DASHID=x3g4Wx5ik
curl -X GET -H "Authorization: Bearer $APIKEY" $GURL/api/dashboards/uid/$DASHID -o dashboard.json

Now create the snapshot via a call to the respective API endpoint. Note that here we directly submit the dashboard JSON of which we'd like a snapshot.

curl -X POST -H "Authorization: Bearer $APIKEY" -H "Content-Type: application/json" -d @dashboard.json $GURL/api/snapshots -o snapshot.json

The result is saved in snapshot.json. From this we can extract the URL of the generated snapshot.

export SNAPURL=`jq .url snapshot.json`

Now export to PDF with

node pdf.js $SNAPURL output.pdf
/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const puppeteer = require('puppeteer');
// URL to load should be passed as first parameter
const url = process.argv[2].replace (/(^")|("$)/g, '');
// Output file name should be second parameter
const outfile = process.argv[3];
// TODO: Output an error message if number of arguments is not right or arguments are invalid
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url, {waitUntil: 'networkidle2'});
// Wait for any warnings to disappear
await page.waitFor(10000);
// page.pdf() is currently supported only in headless mode.
// @see https://bugs.chromium.org/p/chromium/issues/detail?id=753118
await page.pdf({
path: outfile,
format: 'A4',
scale: 0.75,
displayHeaderFooter: false,
printBackground: false,
margin: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
});
await browser.close();
})();
@vijay-v6
Copy link

vijay-v6 commented Dec 5, 2020

Hi, Does this pdf export includes all the panels within the dashboard or the list of dashboards that is parsed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment