Skip to content

Developing Grafana plugins

Rasmus Appelqvist edited this page May 10, 2017 · 15 revisions

We have developed three Grafana plugins. Our research about developing plugins for Grafana has been done using Grafana's documentation and by looking at source code from Grafana and other plugins.

Structure

The basic structure and style for developing Grafana plugins can be found here.

We have used npm and Grunt for automatic builds. The plugins are written in an ES6 standard in JavaScript and all code is transpiled into an ES5 standard with babel and bundled using Browserify to work with Grafana.

Our plugin directory has the following structure:

<plugin folder>
  |--images
       |--<images>
  |--src
       |--module.js // For loading Grafana's SDK
       |--module.html // Main HTML for panel
       |--package.json // For using npm to install D3 in src so that it's copied to dist for use in Grafana.
       |--<Angular controller class inheriting from Grafana's SDK>
       |--<Other classes>
  |--test
       |--<tests for classes> // Note that we cannot test classes inheriting from Grafana's SDK
  |--Gruntfile.js
  |--karma.conf.js // For testing
  |--package.json // For npm
  |--plugin.json // For grafana
  |--README.md

We are using grunt to transpile the js-files in src to dist. Grafana uses the dist folder, so everything needed for the plugin has to be copied there.

Grafana's SDK

From here we are importing Grafana's SDK that has panel-controller-classes and support for designing for both dark and light theme. As you can see here we are exporting our implemented controller as Grafana's PanelCtrl, which will make sure that our controller is set as the controller for the plugin-panel. This is done in module.js.

module.js

Our controllers are inheriting from Grafana's MericsPanelCtrl that has listeners and functions for receiving data from a Grafana datasource. For example the function:

onDataReceived(dataList)

will run when new data is received. There are also other functions such as loading snapshots or implementing custom options for your plugin.

The controller has a constructor where for example angular's scope is injected. We are also injecting for example variableSrv that is needed for handling variables. The panelDefaults variable is set as panel settings that are available as:

this.panel.<setting-name>

These are used when adding user options for the panel and will be saved together with the panel. ctrl

Setting events. ctrl

We also have to set the html-file for the panel as such: set html

HTML

The HTML is connected to the controller and can be used with angular directives. The controller's variables can be accessed with the ctrl.-prefix.

For examples see Heatmap and GeoMap.

D3 library

To include D3 the library has to be present in the dist directory to be found when the plugin is loaded in Grafana. We have solved this by adding D3 as a dependency in the src-folder. This means that

npm install

has to be run inside the src-folder once for the panel to find D3. We have chosen to add grunt-auto-install to our Grunt. When Grunt is run npm will be run first. This is for production. For development we have also defined another grunt-task that can be run without running npm install. You can see our Gruntfile here.

Templates

By defining templates in Grafana data can be shared between different plugins. For example in our dashboard we share data between our own plugins and Grafana'a graph plugin. These templates are setup by an admin user. The templates used in our plugins are described in our plugins readmes. However, we also wanted the functionality to select a certain product or country by clicking in our panel. To do this we implemented our own TemplateHandler for creating variables programatically. The code to the TemplateHandler-class can be found here.

In order to handle template variables programatically, we need to inject variableSrv and templateSrv into our controller. We then add the variable to the variableSrv and initiate it into the templateSrv in order to make it a template variable. Lastly, we need to broadcast to the dashboard that a new template variable has been added. When editing or deleting a template variable, we'll need to find the variable inside the variableSrv and make changes to it. When changes have been made we will again need to initiate it to the templateSrc and broadcast the changes to the dashboard.

Clone this wiki locally