Lately I’v been toying with some sensors at home, for which data ends up in a VictoriaMetrics instance and gets displayed using Grafana dashboards.
Setting this up was surprinsingly easy. At some point I wondered whether I could get the charts to be displayed on a Pimoroni e-ink display that I own.
Again, surprisingly, I found that Grafana supposedly allows you to genereate a PNG for any chart extremely easily. I write supposedly because it ended up taking a bit longer than expected:
Out of bad luck or plain lack of skill, I could not find any place clearly lining out the required steps.
So here’s how to get PNG images out of your Grafana charts, assuming you have a running Grafana instance:
Generate Images from a Grafana chart
Here are the steps. Details in links or below:
- Enable image generation
- either install the relevant plugin (won’t work for all architectures, for example Synology)
- run a separate renderer service (easy if your installation is docker-based, and it works on a Synology)
- Find the dashboard and view ID:
- Decide on the authentication approach: (anonymous, user/password or token)
- query the right url: the annoying part that took the longest
1. Enable Image generation
It’s not obviously clear that, in order to have Grafana generate fixed images, you need to either enable the right plugin or tell Grafana to query a separate rendering endpoint
If your Grafana instance is running on a compatible os+architecture combination and you’re Ok with and able to install a plugin, follow the steps to obtain grafana-image-renderer.
If you’re stuck on an incompatible os+architecture (such as certain Synology versions), your only other option is to run the renderer as a separate docker image and tell Grafana how to use it.
That second option is very easy to setup if you have a minimum of familiarity with docker. Grafana’s repo has a minimal sample docker-compose.yaml file.
Below is a slightly extended one that includes the flags to allow anonymous access if your main interest is to get to the images quickly:
version: '2'
services:
grafana:
image: grafana/grafana:latest
ports:
- 3000
environment:
GF_RENDERING_SERVER_URL: http://renderer:8081/render # <-- tells Grafana where to find the rendere
GF_RENDERING_CALLBACK_URL: http://grafana:3000 # <-- tells the renderer where to access Grafana
GF_LOG_FILTERS: rendering: debug # <-- useful for troubleshooting
GF_AUTH_ANONYMOUS_ENABLED: true # <-- If you want to skip setting/using credentials for generating images
GF_RENDERING_AUTH_TOKEN: changeThisToken # <-- authentication token the renderer will use
renderer:
image: grafana/grafana-image-renderer:latest # <-- renderer image. Probably works on your ARM or Synology!
ports:
- 8081
volumes:
- ./config.json:/usr/src/app/config.json # <-- config that needs to contain the token under GF_RENDERING_AUTH_TOKEN above
If your Grafana instance is already running as a docker container, starting a grafana/grafana-image-renderer
next to it and adding the relevant environment variables is all that is needed.
2. Find the dashboard and view ID
First, navigate to the dashboard that contains the chart or panel you’d like to render an image of. The URL will ressemble this:
http://<host>/d/b4e5c9b9-bff7-4545-8ab2-6b3466b57e6a/home?orgId=1
Above, the uuid (here b4e5c9b9-bff7-4545-8ab2-6b3466b57e6a
) corresponds to your dashboard ID. You’ll also want to remember the orgId
.
To figure out the panel Id, find the share option for the panel you want to render, and click on the embed tab: the displayed HTML code will contain an URL with a &panelId=
parameter: that’s what you are looking for.
(Alternatively, the link tab provides you with a link that has a &viewPanel=
parameter, which also contains the ID we’re after)
The /home
in the URL is the dashboard’s name. It is not required for generating PNGs.
3. (Optional) Using Credentials
As for passing credentials to Grafana when generating the image, you have multiple options:
- nothing: if your instance allows anonymous access, there is nothing to do.
- username/password: you can specify the user and password in the URL you will query: eg with
curl
:curl 'http://<username>:<password>@<grafana_hostname>/<rendering_path>'
- token: Grafana lets you define service accounts for which you can generate a token. Once you have one you can use it to authenticate. With
curl
:curl "Authorization: Bearer <TOKEN>" 'http://<grafana_hostname>/<rendering_path>'
Note that if you’re not using SSL because, for example, you’re on your local home network, it might be worth considering not to use your admin credentials in cleartext with each request…
4. Query the right URL
And here’s the easiest part that, nonetheless took me the longest to figure out: querying the right URL
It is in the form http://<grafana_host>/render/d-solo/<dashboard_id>?orgId=<orgId>&from=<from_timestamp_millis>&to=<to_timestamp_millis>&panelId=<panelId>&width=600&height=448&tz=Europe%2FZurich&theme=light
(If you prefer the dark theme, you may set &theme=dark
at the end.)
As an example, Packing it all together with curl
, you’d end up with something like:
curl "http://192.168.1.5:3030/render/d-solo/b4e5c9b9-bff7-4545-8ab2-6b3466b57e6a?orgId=1&from=1714240164000&to=1714248164000&panelId=6&width=600&height=448&tz=Europe%2FZurich&theme=light" -o chart.png
Note: this worked for me using Grafana version 10.3.5, running via Docker on Synology DS918+
Happy PNG rendering!