Docs: Plugins doc reorganization, part 1 (#69864)

* Initial commit

* Prettier fixes

* Doc-validator fixes part 1

* Doc-validator fixes part 2

* More doc-validator fixes

* More doc-validator fixes

* Test

* link test

* Linnk test

* Link test

* More fixes

* More fixes

* Doc-validator fixes

* Doc-validator fixes

* fix broken link

* Fix

* Testing

* Doc fixes

* Link fixes

* Fix links

* Update docs/sources/developers/plugins/create-a-grafana-plugin/_index.md

Co-authored-by: David Harris <david.harris@grafana.com>

* Testing

* Testing

* Testing

* Testing

* Doc-validator fixes

* Doc-validator fixes

* Doc-validator fixes

* Fix broken links for plugins reorganization project

* Prettier fixes

* Prettier fixes

* Incorporate reviewer feedback

* Link fixes

* Link fixes

* Link fixes

* Link fix

* Deleted space

* Codeowners fix

* Change grafana.com links to absolute URLs for Hugo

---------

Co-authored-by: David Harris <david.harris@grafana.com>
This commit is contained in:
Joseph Perez
2023-07-05 11:25:11 -07:00
committed by GitHub
parent bdf60d69de
commit f9df1f3051
70 changed files with 563 additions and 412 deletions

View File

@ -1,8 +1,9 @@
---
title: Grafana plugin developer's guide
menuTitle: Plugin developer's guide
aliases:
- ../plugins/developing/
description: Resources for creating Grafana plugins
title: Plugin developer's guide
weight: 200
---
@ -10,7 +11,7 @@ weight: 200
You can extend Grafana's built-in capabilities with plugins. Plugins enable Grafana to accomplish specialized tasks, custom-tailored to your requirements. By making a plugin for your organization, you can connect Grafana to other data sources, ticketing tools, and CI/CD tooling.
You can create plugins for private use or contribute them to the open source community by publishing to the [Grafana plugin catalog](https://grafana.com/grafana/plugins/). This catalog has hundreds of other community and commercial plugins.
You can create plugins for private use or contribute them to the open source community by publishing to the [Grafana plugin catalog](/grafana/plugins/). This catalog has hundreds of other community and commercial plugins.
If you are a Grafana plugin developer or want to become one, this plugin developer's guide contains the tutorials and reference materials to help you get started.
@ -28,12 +29,13 @@ You can create several types of plugins, including:
The following topics are covered in this guide:
- **[Get started with plugins]({{< relref "./get-started-with-plugins" >}})** - Start developing Grafana plugins with the [Create-plugin](https://www.npmjs.com/package/@grafana/create-plugin) tool.
- **[Introduction to plugin development]({{< relref "./introduction-to-plugin-development" >}})** - Learn the fundamentals of Grafana plugin development: frontend and backend development processes, data frames, error handling, and more.
- **[Create a Grafana plugin]({{< relref "./create-a-grafana-plugin" >}})** - If you're familiar with plugin creation, use the tutorials for creating panel plugins, data source plugins, and more to deepen your knowledge.
- **[Migrate a plugin]({{< relref "./migration-guide" >}})** - Learn how to upgrade from a previous version of a Grafana plugin, rewrite an old Angular plugin in React, or update to a newer version.
- **[Introduction to plugin development]({{< relref "./introduction-to-plugin-development" >}})** - Learn the fundamentals of Grafana plugin development: backend development, data frames, error handling, and more.
- **[Get started with plugins]({{< relref "./get-started-with-plugins" >}})** - Start developing Grafana plugins with the [create-plugin](https://www.npmjs.com/package/@grafana/create-plugin) tool.
- **[Create a Grafana plugin]({{< relref "./create-a-grafana-plugin/_index.md" >}})** - If you're familiar with plugin creation, use the tutorials for creating panel plugins, data source plugins, and more to deepen your knowledge.
- **[Publish a Grafana plugin]({{< relref "./publish-a-plugin" >}})** - Learn about publishing a plugin to the Grafana plugin catalog, including publishing criteria, packaging, and deployment.
- **[Reference]({{< relref "metadata.md" >}})** - Description of the `plugin.json` schema and plugin metadata.
- **[Work with legacy plugins]({{< relref "./legacy" >}})** - Learn how to upgrade from a previous version of a Grafana plugin, rewrite an old Angular plugin in React, or update to a newer version.
- **[Migrate a plugin]({{< relref "./migration-guide" >}})** - Consult these documents if you need to work with a plugin written in deprecated technology.
- **[Reference]({{< relref "./metadata.md" >}})** - Description of the `plugin.json` schema and plugin metadata.
## Go further
@ -49,4 +51,4 @@ Grafana Labs provides a number of best practice example plugins for different us
### SDK
Learn more about [Grafana Plugin SDK for Go]({{< relref "./backend/grafana-plugin-sdk-for-go" >}}).
Learn more about [Grafana Plugin SDK for Go]({{< relref "./introduction-to-plugin-development/backend/grafana-plugin-sdk-for-go" >}}).

View File

@ -1,27 +1,18 @@
---
description: How-to topics for plugin development
title: Create a plugin
title: Create a Grafana plugin
menuTitle: Create a plugin
keywords:
- grafana
- plugins
- plugin
- documentation
description: An index of how-to topics for Grafana plugin development.
weight: 300
---
# Create a Grafana plugin
This section contains how-to topics for developing Grafana plugins.
This section contains how-to topics for developing and extending Grafana plugins with more advanced capabilities.
- [Build a Grafana plugin](https://grafana.github.io/plugin-tools/docs/creating-a-plugin)
- [Build a panel plugin](https://grafana.com/tutorials/build-a-panel-plugin/)
- [Build a data source plugin](https://grafana.com/tutorials/build-a-data-source-plugin/)
- [Build a data source backend plugin](https://grafana.com/tutorials/build-a-data-source-backend-plugin/)
- [Build a logs data source plugin]({{< relref "../build-a-logs-data-source-plugin.md">}})
- [Build a streaming data source plugin]({{< relref "../build-a-streaming-data-source-plugin.md">}})
- Extend a Grafana plugin
- [Add annotations]({{< relref "add-support-for-annotations.md">}})
- [Add anonymous usage reporting]({{< relref "add-anonymous-usage-reporting.md">}})
- [Add authentication for a data source plugin]({{< relref "add-authentication-for-data-source-plugins.md">}})
- [Add Explore queries]({{< relref "add-support-for-explore-queries.md">}})
- [Add query editor help]({{< relref "add-query-editor-help.md">}})
- [Add variables]({{< relref "add-support-for-variables.md">}})
- [Create panel option editors]({{< relref "custom-panel-option-editors.md">}})
- [Sign a plugin]({{< relref "sign-a-plugin.md">}})
- [Automate development with CI](https://grafana.github.io/plugin-tools/docs/ci)
- [Create nested plugins](https://grafana.github.io/plugin-tools/docs/nested-plugins)
- [Extend configurations](https://grafana.github.io/plugin-tools/docs/advanced-configuration)
- [Develop a plugin]({{< relref "./develop-a-plugin" >}})
- [Extend a plugin]({{< relref "./extend-a-plugin" >}})

View File

@ -0,0 +1,28 @@
---
title: Develop a Grafana plugin
menuTitle: Develop a plugin
keywords:
- grafana
- plugins
- plugin
- development
- documentation
description: An index of how-to topics for Grafana plugin development.
weight: 100
---
# Develop a Grafana plugin
This section contains how-to topics for developing Grafana plugins:
- [Build a panel plugin]({{< relref "./build-a-panel-plugin.md" >}})
- [Build a panel plugin with d3.js]({{< relref "./build-a-panel-plugin-with-d3.md" >}})
- [Build a data source plugin]({{< relref "./build-a-data-source-plugin.md" >}})
- [Build a data source backend plugin]({{< relref "./build-a-data-source-backend-plugin.md" >}})
- [Build a logs data source plugin]({{< relref "./build-a-logs-data-source-plugin.md" >}})
- [Build a streaming data source plugin]({{< relref "./build-a-streaming-data-source-plugin.md" >}})
- [Work with data frames]({{< relref "./working-with-data-frames.md" >}})
Additional resources:
- [Build a Grafana plugin with the create-plugin tool](https://grafana.github.io/plugin-tools/docs/creating-a-plugin)

View File

@ -0,0 +1,184 @@
---
title: Build a data source backend plugin
description: Create a backend for your data source plugin.
weight: 400
keywords:
- grafana
- plugins
- plugin
- backend
- backend data source
- datasource
---
## Introduction
Grafana supports a wide range of data sources, including Prometheus, MySQL, and even Datadog. There's a good chance you can already visualize metrics from the systems you have set up. In some cases, though, you already have an in-house metrics solution that youd like to add to your Grafana dashboards. This tutorial teaches you to build a support for your data source.
For more information about backend plugins, refer to the documentation on [Backend plugins](/docs/grafana/latest/developers/plugins/backend/).
In this tutorial, you'll:
- Build a backend for your data source
- Implement a health check for your data source
- Enable Grafana Alerting for your data source
{{% class "prerequisite-section" %}}
#### Prerequisites
- Knowledge about how data sources are implemented in the frontend.
- Grafana 7.0
- Go ([Version](https://github.com/grafana/plugin-tools/blob/main/packages/create-plugin/templates/backend/go.mod#L3))
- [Mage](https://magefile.org/)
- NodeJS ([Version](https://github.com/grafana/plugin-tools/blob/main/packages/create-plugin/templates/common/package.json#L66))
- yarn
{{% /class %}}
## Set up your environment
{{< docs/shared lookup="tutorials/set-up-environment.md" source="grafana" version="latest" >}}
## Create a new plugin
To build a backend for your data source plugin, Grafana requires a binary that it can execute when it loads the plugin during start-up. In this guide, we will build a binary using the [Grafana plugin SDK for Go]({{< relref "../../introduction-to-plugin-development/backend/grafana-plugin-sdk-for-go" >}}).
The easiest way to get started is to use the Grafana [create-plugin tool](https://www.npmjs.com/package/@grafana/create-plugin). Navigate to the plugin folder that you configured in step 1 and type:
```
npx @grafana/create-plugin@latest
```
Follow the steps and select **datasource** as your plugin type and answer **yes** when prompted to create a backend for your plugin.
```bash
cd my-plugin
```
Install frontend dependencies and build frontend parts of the plugin to _dist_ directory:
```bash
yarn install
yarn build
```
Run the following to update [Grafana plugin SDK for Go]({{< relref "../../introduction-to-plugin-development/backend/grafana-plugin-sdk-for-go" >}}) dependency to the latest minor version:
```bash
go get -u github.com/grafana/grafana-plugin-sdk-go
go mod tidy
```
Build backend plugin binaries for Linux, Windows and Darwin to _dist_ directory:
```bash
mage -v
```
Now, let's verify that the plugin you've built so far can be used in Grafana when creating a new data source:
1. Restart your Grafana instance.
1. Open Grafana in your web browser.
1. Navigate via the side-menu to **Configuration** -> **Data Sources**.
1. Click **Add data source**.
1. Find your newly created plugin and select it.
1. Enter a name and then click **Save & Test** (ignore any errors reported for now).
You now have a new data source instance of your plugin that is ready to use in a dashboard:
1. Navigate via the side-menu to **Create** -> **Dashboard**.
1. Click **Add new panel**.
1. In the query tab, select the data source you just created.
1. A line graph is rendered with one series consisting of two data points.
1. Save the dashboard.
### Troubleshooting
#### Grafana doesn't load my plugin
By default, Grafana requires backend plugins to be signed. To load unsigned backend plugins, you need to
configure Grafana to [allow unsigned plugins](/docs/grafana/latest/plugins/plugin-signature-verification/#allow-unsigned-plugins).
For more information, refer to [Plugin signature verification](/docs/grafana/latest/plugins/plugin-signature-verification/#backend-plugins).
## Anatomy of a backend plugin
The folders and files used to build the backend for the data source are:
| file/folder | description |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Magefile.go` | Its not a requirement to use mage build files, but we strongly recommend using it so that you can use the build targets provided by the plugin SDK. |
| `/go.mod ` | Go modules dependencies, [reference](https://golang.org/cmd/go/#hdr-The_go_mod_file) |
| `/src/plugin.json` | A JSON file describing the backend plugin |
| `/pkg/main.go` | Starting point of the plugin binary. |
#### plugin.json
The [plugin.json](/docs/grafana/latest/developers/plugins/metadata/) file is required for all plugins. When building a backend plugin these properties are important:
| property | description |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| backend | Should be set to `true` for backend plugins. This tells Grafana that it should start a binary when loading the plugin. |
| executable | This is the name of the executable that Grafana expects to start, see [plugin.json reference](/docs/grafana/latest/developers/plugins/metadata/) for details. |
| alerting | Should be set to `true` if your backend datasource supports alerting. |
In the next step we will look at the query endpoint!
## Implement data queries
We begin by opening the file `/pkg/plugin/plugin.go`. In this file you will see the `SampleDatasource` struct which implements the [backend.QueryDataHandler](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go/backend?tab=doc#QueryDataHandler) interface. The `QueryData` method on this struct is where the data fetching happens for a data source plugin.
Each request contains multiple queries to reduce traffic between Grafana and plugins. So you need to loop over the slice of queries, process each query, and then return the results of all queries.
In the tutorial we have extracted a method named `query` to take care of each query model. Since each plugin has their own unique query model, Grafana sends it to the backend plugin as JSON. Therefore the plugin needs to `Unmarshal` the query model into something easier to work with.
As you can see the sample only returns static numbers. Try to extend the plugin to return other types of data.
You can read more about how to [build data frames in our docs](/docs/grafana/latest/developers/plugins/data-frames/).
## Add support for health checks
Implementing the health check handler allows Grafana to verify that a data source has been configured correctly.
When editing a data source in Grafana's UI, you can **Save & Test** to verify that it works as expected.
In this sample data source, there is a 50% chance that the health check will be successful. Make sure to return appropriate error messages to the users, informing them about what is misconfigured in the data source.
Open `/pkg/plugin/plugin.go`. In this file you'll see that the `SampleDatasource` struct also implements the [backend.CheckHealthHandler](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go/backend?tab=doc#CheckHealthHandler) interface. Navigate to the `CheckHealth` method to see how the health check for this sample plugin is implemented.
## Add authentication
Implementing authentication allows your plugin to access protected resources like databases or APIs. To learn more about how to authenticate using a backend plugin, refer to [our documentation]({{< relref "../extend-a-plugin/add-authentication-for-data-source-plugins/#authenticate-using-a-backend-plugin" >}}).
## Enable Grafana Alerting
1. Open _src/plugin.json_.
1. Add the top level `backend` property with a value of `true` to specify that your plugin supports Grafana Alerting, e.g.
```json
{
...
"backend": true,
"executable": "gpx_simple_datasource_backend",
"alerting": true,
"info": {
...
}
```
1. Rebuild frontend parts of the plugin to _dist_ directory:
```bash
yarn build
```
1. Restart your Grafana instance.
1. Open Grafana in your web browser.
1. Open the dashboard you created earlier in the _Create a new plugin_ step.
1. Edit the existing panel.
1. Click on the _Alert_ tab.
1. Click on _Create Alert_ button.
1. Edit condition and specify _IS ABOVE 10_. Change _Evaluate every_ to _10s_ and clear the _For_ field to make the alert rule evaluate quickly.
1. Save the dashboard.
1. After some time the alert rule evaluates and transitions into _Alerting_ state.
## Summary
In this tutorial you created a backend for your data source plugin.

View File

@ -0,0 +1,376 @@
---
title: Build a data source plugin
description: Create a plugin to add support for your own data sources.
weight: 300
keywords:
- grafana
- plugins
- plugin
- data source
- datasource
---
## Introduction
Grafana supports a wide range of data sources, including Prometheus, MySQL, and even Datadog. There's a good chance you can already visualize metrics from the systems you have set up. In some cases, though, you already have an in-house metrics solution that youd like to add to your Grafana dashboards. This tutorial teaches you to build a support for your data source.
In this tutorial, you'll:
- Build a data source to visualize a sine wave
- Construct queries using the query editor
- Configure your data source using the config editor
{{% class "prerequisite-section" %}}
### Prerequisites
- Grafana >=7.0
- NodeJS >=14
- yarn
{{% /class %}}
## Set up your environment
{{< docs/shared lookup="tutorials/set-up-environment.md" source="grafana" version="latest" >}}
## Create a new plugin
{{< docs/shared lookup="tutorials/create-plugin.md" source="grafana" version="latest" >}}
To learn how to create a backend data source plugin, see [Build a data source backend plugin]({{< relref "./build-a-data-source-backend-plugin.md" >}})
## Anatomy of a plugin
{{< docs/shared lookup="tutorials/plugin-anatomy.md" source="grafana" version="latest" >}}
## Data source plugins
A data source in Grafana must extend the `DataSourceApi` interface, which requires you to define two methods: `query` and `testDatasource`.
### The `query` method
The `query` method is the heart of any data source plugin. It accepts a query from the user, retrieves the data from an external database, and returns the data in a format that Grafana recognizes.
```
async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse>
```
The `options` object contains the queries, or _targets_, that the user made, along with context information, like the current time interval. Use this information to query an external database.
> The term _target_ originates from Graphite, and the earlier days of Grafana when Graphite was the only supported data source. As Grafana gained support for more data sources, the term "target" became synonymous with any type of query.
### Test your data source
`testDatasource` implements a health check for your data source. For example, Grafana calls this method whenever the user clicks the **Save & Test** button, after changing the connection settings.
```
async testDatasource()
```
## Data frames
Nowadays there are countless different databases, each with their own ways of querying data. To be able to support all the different data formats, Grafana consolidates the data into a unified data structure called _data frames_.
Let's see how to create and return a data frame from the `query` method. In this step, you'll change the code in the starter plugin to return a [sine wave](https://en.wikipedia.org/wiki/Sine_wave).
1. In the current `query` method, remove the code inside the `map` function.
The `query` method now look like this:
```ts
async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
const { range } = options;
const from = range!.from.valueOf();
const to = range!.to.valueOf();
const data = options.targets.map(target => {
// Your code goes here.
});
return { data };
}
```
1. In the `map` function, use the `lodash/defaults` package to set default values for query properties that haven't been set:
```ts
const query = defaults(target, defaultQuery);
```
1. Create a default query at the top of datasource.ts:
```ts
export const defaultQuery: Partial<MyQuery> = {
constant: 6.5,
};
```
1. Create a data frame with a time field and a number field:
```ts
const frame = new MutableDataFrame({
refId: query.refId,
fields: [
{ name: 'time', type: FieldType.time },
{ name: 'value', type: FieldType.number },
],
});
```
`refId` needs to be set to tell Grafana which query that generated this date frame.
Next, we'll add the actual values to the data frame. Don't worry about the math used to calculate the values.
1. Create a couple of helper variables:
```ts
// duration of the time range, in milliseconds.
const duration = to - from;
// step determines how close in time (ms) the points will be to each other.
const step = duration / 1000;
```
1. Add the values to the data frame:
```ts
for (let t = 0; t < duration; t += step) {
frame.add({ time: from + t, value: Math.sin((2 * Math.PI * t) / duration) });
}
```
The `frame.add()` accepts an object where the keys corresponds to the name of each field in the data frame.
1. Return the data frame:
```ts
return frame;
```
1. Rebuild the plugin and try it out.
Your data source is now sending data frames that Grafana can visualize. Next, we'll look at how you can control the frequency of the sine wave by defining a _query_.
> In this example, we're generating timestamps from the current time range. This means that you'll get the same graph no matter what time range you're using. In practice, you'd instead use the timestamps returned by your database.
## Define a query
Most data sources offer a way to query specific data. MySQL and PostgreSQL use SQL, while Prometheus has its own query language, called _PromQL_. No matter what query language your databases are using, Grafana lets you build support for it.
Add support for custom queries to your data source, by implementing your own _query editor_, a React component that enables users to build their own queries, through a user-friendly graphical interface.
A query editor can be as simple as a text field where the user edits the raw query text, or it can provide a more user-friendly form with drop-down menus and switches, that later gets converted into the raw query text before it gets sent off to the database.
### Define the query model
The first step in designing your query editor is to define its _query model_. The query model defines the user input to your data source.
We want to be able to control the frequency of the sine wave, so let's add another property.
1. Add a new number property called `frequency` to the query model:
**src/types.ts**
```ts
export interface MyQuery extends DataQuery {
queryText?: string;
constant: number;
frequency: number;
}
```
1. Set a default value to the new `frequency` property:
```ts
export const defaultQuery: Partial<MyQuery> = {
constant: 6.5,
frequency: 1.0,
};
```
### Bind the model to a form
Now that you've defined the query model you wish to support, the next step is to bind the model to a form. The `FormField` is a text field component from `grafana/ui` that lets you register a listener which will be invoked whenever the form field value changes.
1. Define the `frequency` from the `query` object and add a new form field to the query editor to control the new frequency property in the `render` method.
**QueryEditor.tsx**
```ts
const { queryText, constant, frequency } = query;
```
```ts
<InlineField label="Frequency" labelWidth={16}>
<Input onChange={onFrequencyChange} value={frequency} />
</InlineField>
```
1. Add a event listener for the new property.
```ts
const onFrequencyChange = (event: ChangeEvent<HTMLInputElement>) => {
onChange({ ...query, frequency: parseFloat(event.target.value) });
// executes the query
onRunQuery();
};
```
The registered listener, `onFrequencyChange`, calls `onChange` to update the current query with the value from the form field.
`onRunQuery();` tells Grafana to run the query after each change. For fast queries, this is recommended to provide a more responsive experience.
### Use the property
The new query model is now ready to use in our `query` method.
1. In the `query` method, use the `frequency` property to adjust our equation.
```ts
frame.add({ time: from + t, value: Math.sin((2 * Math.PI * query.frequency * t) / duration) });
```
## Configure your data source
To access a specific data source, you often need to configure things like hostname, credentials, or authentication method. A _config editor_ lets your users configure your data source plugin to fit their needs.
The config editor looks similar to the query editor, in that it defines a model and binds it to a form.
Since we're not actually connecting to an external database in our sine wave example, we don't really need many options. To show you how you can add an option however, we're going to add the _wave resolution_ as an option.
The resolution controls how close in time the data points are to each other. A higher resolution means more points closer together, at the cost of more data being processed.
### Define the options model
1. Add a new number property called `resolution` to the options model.
**types.ts**
```ts
export interface MyDataSourceOptions extends DataSourceJsonData {
path?: string;
resolution?: number;
}
```
### Bind the model to a form
Just like query editor, the form field in the config editor calls the registered listener whenever the value changes.
1. Add a new form field to the query editor to control the new resolution option.
**ConfigEditor.tsx**
```ts
<InlineField label="Resolution" labelWidth={12}>
<Input onChange={onResolutionChange} value={jsonData.resolution || ''} placeholder="Enter a number" width={40} />
</InlineField>
```
1. Add a event listener for the new option.
```ts
const onResolutionChange = (event: ChangeEvent<HTMLInputElement>) => {
const jsonData = {
...options.jsonData,
resolution: parseFloat(event.target.value),
};
onOptionsChange({ ...options, jsonData });
};
```
The `onResolutionChange` listener calls `onOptionsChange` to update the current options with the value from the form field.
### Use the option
1. Create a property called `resolution` to the `DataSource` class.
```ts
export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
resolution: number;
constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>) {
super(instanceSettings);
this.resolution = instanceSettings.jsonData.resolution || 1000.0;
}
// ...
```
1. In the `query` method, use the `resolution` property to calculate the step size.
**src/datasource.ts**
```ts
const step = duration / this.resolution;
```
## Get data from an external API
So far, you've generated the data returned by the data source. A more realistic use case would be to fetch data from an external API.
While you can use something like [axios](https://github.com/axios/axios) or the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to make requests, we recommend using the [`getBackendSrv` function](https://github.com/grafana/grafana/blob/main/packages/grafana-runtime/src/services/backendSrv.ts) from the [`grafana-runtime` package](https://github.com/grafana/grafana/tree/main/packages/grafana-runtime).
The main advantage of `getBackendSrv` is that it proxies requests through the Grafana server rather making the request from the browser. This is strongly recommended when making authenticated requests to an external API. For more information on authenticating external requests, refer to [Add authentication for data source plugins]({{< relref "../extend-a-plugin/add-authentication-for-data-source-plugins.md" >}}).
1. Import `getBackendSrv`.
**src/datasource.ts**
```ts
import { getBackendSrv } from '@grafana/runtime';
```
1. Create a helper method `doRequest` and use the `datasourceRequest` method to make a request to your API. Replace `https://api.example.com/metrics` to point to your own API endpoint.
```ts
async doRequest(query: MyQuery) {
const result = await getBackendSrv().datasourceRequest({
method: "GET",
url: "https://api.example.com/metrics",
params: query,
})
return result;
}
```
1. Make a request for each query. `Promises.all` waits for all requests to finish before returning the data.
```ts
async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
const promises = options.targets.map((query) =>
this.doRequest(query).then((response) => {
const frame = new MutableDataFrame({
refId: query.refId,
fields: [
{ name: "Time", type: FieldType.time },
{ name: "Value", type: FieldType.number },
],
});
response.data.forEach((point: any) => {
frame.appendRow([point.time, point.value]);
});
return frame;
})
);
return Promise.all(promises).then((data) => ({ data }));
}
```
## Summary
In this tutorial you built a complete data source plugin for Grafana that uses a query editor to control what data to visualize. You've added a data source option, commonly used to set connection options and more.
### Learn more
Learn how you can improve your plugin even further, by reading our advanced guides:
- [Add support for variables](/docs/grafana/latest/developers/plugins/add-support-for-variables/)
- [Add support for annotations](/docs/grafana/latest/developers/plugins/add-support-for-annotations/)
- [Add support for Explore queries](/docs/grafana/latest/developers/plugins/add-support-for-explore-queries/)
- [Build a logs data source](/docs/grafana/latest/developers/plugins/build-a-logs-data-source-plugin/)

View File

@ -1,5 +1,16 @@
---
title: Build a logs data source plugin
description: How to build a logs data source plugin.
aliases:
- ../../../plugins/build-a-logs-data-source-plugin/
keywords:
- grafana
- plugins
- plugin
- logs
- logs data source
- datasource
weight: 500
---
# Build a logs data source plugin
@ -8,7 +19,7 @@ Grafana data source plugins support metrics, logs, and other data types. The ste
## Before you begin
This guide assumes that you're already familiar with how to [Build a data source plugin](/tutorials/build-a-data-source-plugin/) for metrics. We recommend that you review this material before continuing.
This guide assumes that you're already familiar with how to [Build a data source plugin]({{< relref "./build-a-data-source-plugin" >}}) for metrics. We recommend that you review this material before continuing.
## Add logs support to your data source
@ -21,7 +32,7 @@ When these steps are done, then you can improve the user experience with one or
### Step 1: Enable logs support
Tell Grafana that your data source plugin can return log data, by adding `"logs": true` to the [plugin.json]({{< relref "metadata/" >}}) file.
Tell Grafana that your data source plugin can return log data, by adding `"logs": true` to the [plugin.json]({{< relref "../../metadata.md" >}}) file.
```json
{
@ -31,7 +42,7 @@ Tell Grafana that your data source plugin can return log data, by adding `"logs"
### Step 2: Construct the log data
As it does with metrics data, Grafana expects your plugin to return log data as a [data frame]({{< relref "data-frames/" >}}).
As it does with metrics data, Grafana expects your plugin to return log data as a [data frame]({{< relref "../../introduction-to-plugin-development/data-frames.md" >}}).
To return log data, return a data frame with at least one time field and one text field from the data source's `query` method.
@ -50,7 +61,7 @@ frame.add({ time: 1589189388597, content: 'user registered' });
frame.add({ time: 1589189406480, content: 'user logged in' });
```
That's all you need to start returning log data from your data source. Go ahead and try it out in [Explore]({{< relref "../../explore/" >}}) or by adding a [Logs panel]({{< relref "../../panels-visualizations/visualizations/logs/" >}}).
That's all you need to start returning log data from your data source. Go ahead and try it out in [Explore]({{< relref "../../../../explore" >}}) or by adding a [Logs panel]({{< relref "../../../../panels-visualizations/visualizations/logs" >}}).
Congratulations, you just wrote your first logs data source plugin! Next, let's look at a couple of features that can further improve the experience for the user.
@ -60,7 +71,7 @@ Add visualization type hints, labels, and other optional features to logs.
### Add a preferred visualization type hint to the data frame
To make sure Grafana recognizes data as logs and shows logs visualization automatically in Explore, set `meta.preferredVisualisationType` to `'logs'` in the returned data frame. See [Selecting preferred visualisation section]({{< relref "add-support-for-explore-queries/#selecting-preferred-visualisation" >}})
To make sure Grafana recognizes data as logs and shows logs visualization automatically in Explore, set `meta.preferredVisualisationType` to `'logs'` in the returned data frame. See [Selecting preferred visualization section]({{< relref "../extend-a-plugin/add-support-for-explore-queries#select-a-preferred-visualization-type" >}})
**Example:**
@ -102,7 +113,7 @@ frame.add({ time: 1589189406480, content: 'user logged in' });
Add additional information about each log line by supplying more data frame fields.
If a data frame has more than one text field, then Grafana assumes the first field in the data frame to be the actual log line. Grafana treats subsequent text fields as [detected fields]({{< relref "../../explore/#labels-and-detected-fields" >}}).
If a data frame has more than one text field, then Grafana assumes the first field in the data frame to be the actual log line. Grafana treats subsequent text fields as detected fields.
Any number of custom fields can be added to your data frame; Grafana comes with two dedicated fields: `levels` and `id`.

View File

@ -0,0 +1,236 @@
---
title: Build a panel plugin with D3.js
description: how to use D3.js in your panel plugins.
weight: 200
keywords:
- grafana
- plugins
- plugin
- d3js
- d3
- panel
- panel plugin
---
## Introduction
Panels are the building blocks of Grafana, and allow you to visualize data in different ways. This tutorial gives you a hands-on walkthrough of creating your own panel using [D3.js](https://d3js.org/).
For more information about panels, refer to the documentation on [Panels](/docs/grafana/latest/features/panels/panels/).
In this tutorial, you'll:
- Build a simple panel plugin to visualize a bar chart.
- Learn how to use D3.js to build a panel using data-driven transformations.
{{% class "prerequisite-section" %}}
### Prerequisites
- Grafana 7.0
- NodeJS 12.x
- yarn
{{% /class %}}
## Set up your environment
{{< docs/shared lookup="tutorials/set-up-environment.md" source="grafana" version="latest" >}}
## Create a new plugin
{{< docs/shared lookup="tutorials/create-plugin.md" source="grafana" version="latest" >}}
## Data-driven documents
[D3.js](https://d3js.org/) is a JavaScript library for manipulating documents based on data. It lets you transform arbitrary data into HTML, and is commonly used for creating visualizations.
Wait a minute. Manipulating documents based on data? That's sounds an awful lot like React. In fact, much of what you can accomplish with D3 you can already do with React. So before we start looking at D3, let's see how you can create an SVG from data, using only React.
In **SimplePanel.tsx**, change `SimplePanel` to return an `svg` with a `rect` element.
```ts
export const SimplePanel = ({ options, data, width, height }: Props) => {
const theme = useTheme();
return (
<svg width={width} height={height}>
<rect x={0} y={0} width={10} height={10} fill={theme.palette.greenBase} />
</svg>
);
};
```
One single rectangle might not be very exciting, so let's see how you can create rectangles from data.
1. Create some data that we can visualize.
```ts
const values = [4, 8, 15, 16, 23, 42];
```
1. Calculate the height of each bar based on the height of the panel.
```ts
const barHeight = height / values.length;
```
1. Inside a SVG group, `g`, create a `rect` element for every value in the dataset. Each rectangle uses the value as its width.
```ts
return (
<svg width={width} height={height}>
<g>
{values.map((value, i) => (
<rect x={0} y={i * barHeight} width={value} height={barHeight - 1} fill={theme.palette.greenBase} />
))}
</g>
</svg>
);
```
1. Rebuild the plugin and reload your browser to see the changes you've made.
As you can see, React is perfectly capable of dynamically creating HTML elements. In fact, creating elements using React is often faster than creating them using D3.
So why would you use even use D3? In the next step, we'll see how you can take advantage of D3's data transformations.
## Transform data using D3.js
In this step, you'll see how you can transform data using D3 before rendering it using React.
D3 is already bundled with Grafana, and you can access it by importing the `d3` package. However, we're going to need the type definitions while developing.
1. Install the D3 type definitions:
```bash
yarn add --dev @types/d3
```
1. Import `d3` in **SimplePanel.tsx**.
```ts
import * as d3 from 'd3';
```
In the previous step, we had to define the width of each bar in pixels. Instead, let's use _scales_ from the D3 library to make the width of each bar depend on the width of the panel.
Scales are functions that map a range of values to another range of values. In this case, we want to map the values in our datasets to a position within our panel.
1. Create a scale to map a value between 0 and the maximum value in the dataset, to a value between 0 and the width of the panel. We'll be using this to calculate the width of the bar.
```ts
const scale = d3
.scaleLinear()
.domain([0, d3.max(values) || 0.0])
.range([0, width]);
```
1. Pass the value to the scale function to calculate the width of the bar in pixels.
```ts
return (
<svg width={width} height={height}>
<g>
{values.map((value, i) => (
<rect x={0} y={i * barHeight} width={scale(value)} height={barHeight - 1} fill={theme.palette.greenBase} />
))}
</g>
</svg>
);
```
As you can see, even if we're using React to render the actual elements, the D3 library contains useful tools that you can use to transform your data before rendering it.
## Add an axis
Another useful tool in the D3 toolbox is the ability to generate _axes_. Adding axes to our chart makes it easier for the user to understand the differences between each bar.
Let's see how you can use D3 to add a horizontal axis to your bar chart.
1. Create a D3 axis. Notice that by using the same scale as before, we make sure that the bar width aligns with the ticks on the axis.
```ts
const axis = d3.axisBottom(scale);
```
1. Generate the axis. While D3 needs to generate the elements for the axis, we can encapsulate it by generating them within an anonymous function which we pass as a `ref` to a group element `g`.
```ts
<g
ref={(node) => {
d3.select(node).call(axis as any);
}}
/>
```
By default, the axis renders at the top of the SVG element. We'd like to move it to the bottom, but to do that, we first need to make room for it by decreasing the height of each bar.
1. Calculate the new bar height based on the padded height.
```ts
const padding = 20;
const chartHeight = height - padding;
const barHeight = chartHeight / values.length;
```
1. Translate the axis by adding a transform to the `g` element.
```ts
<g
transform={`translate(0, ${chartHeight})`}
ref={(node) => {
d3.select(node).call(axis as any);
}}
/>
```
Congrats! You've created a simple and responsive bar chart.
## Complete example
```ts
import React from 'react';
import { PanelProps } from '@grafana/data';
import { SimpleOptions } from 'types';
import { useTheme } from '@grafana/ui';
import * as d3 from 'd3';
interface Props extends PanelProps<SimpleOptions> {}
export const SimplePanel = ({ options, data, width, height }: Props) => {
const theme = useTheme();
const values = [4, 8, 15, 16, 23, 42];
const scale = d3
.scaleLinear()
.domain([0, d3.max(values) || 0.0])
.range([0, width]);
const axis = d3.axisBottom(scale);
const padding = 20;
const chartHeight = height - padding;
const barHeight = chartHeight / values.length;
return (
<svg width={width} height={height}>
<g>
{values.map((value, i) => (
<rect x={0} y={i * barHeight} width={scale(value)} height={barHeight - 1} fill={theme.palette.greenBase} />
))}
</g>
<g
transform={`translate(0, ${chartHeight})`}
ref={(node) => {
d3.select(node).call(axis as any);
}}
/>
</svg>
);
};
```
## Summary
In this tutorial you built a panel plugin with D3.js.

View File

@ -0,0 +1,260 @@
---
title: Build a panel plugin
description: Learn how to create a custom visualization for your dashboards.
weight: 100
keywords:
- grafana
- plugins
- plugin
- visualization
- custom visualization
- dashboard
- dashboards
---
## Introduction
Panels are the building blocks of Grafana. They allow you to visualize data in different ways. While Grafana has several types of panels already built-in, you can also build your own panel, to add support for other visualizations.
For more information about panels, refer to the documentation on [Panels](/docs/grafana/latest/panels/).
{{% class "prerequisite-section" %}}
### Prerequisites
- Grafana >=7.0
- NodeJS >=14
- yarn
{{% /class %}}
## Set up your environment
{{< docs/shared lookup="tutorials/set-up-environment.md" source="grafana" version="latest" >}}
## Create a new plugin
{{< docs/shared lookup="tutorials/create-plugin.md" source="grafana" version="latest" >}}
## Anatomy of a plugin
{{< docs/shared lookup="tutorials/plugin-anatomy.md" source="grafana" version="latest" >}}
## Panel plugins
Since Grafana 6.x, panels are [ReactJS components](https://reactjs.org/docs/components-and-props.html).
Prior to Grafana 6.0, plugins were written in [AngularJS](https://angular.io/). Even though we still support plugins written in AngularJS, we highly recommend that you write new plugins using ReactJS.
### Panel properties
The [PanelProps](https://github.com/grafana/grafana/blob/747b546c260f9a448e2cb56319f796d0301f4bb9/packages/grafana-data/src/types/panel.ts#L27-L40) interface exposes runtime information about the panel, such as panel dimensions, and the current time range.
You can access the panel properties through `props`, as seen in your plugin.
**src/SimplePanel.tsx**
```js
const { options, data, width, height } = props;
```
### Development workflow
Next, you'll learn the basic workflow of making a change to your panel, building it, and reloading Grafana to reflect the changes you made.
First, you need to add your panel to a dashboard:
1. Open Grafana in your browser.
1. Create a new dashboard, and add a new panel.
1. Select your panel from the list of visualization types.
1. Save the dashboard.
Now that you can view your panel, try making a change to the panel plugin:
1. In `SimplePanel.tsx`, change the fill color of the circle.
1. Run `yarn dev` to build the plugin.
1. In the browser, reload Grafana with the new changes.
## Add panel options
Sometimes you want to offer the users of your panel an option to configure the behavior of your plugin. By configuring _panel options_ for your plugin, your panel will be able to accept user input.
In the previous step, you changed the fill color of the circle in the code. Let's change the code so that the plugin user can configure the color from the panel editor.
#### Add an option
Panel options are defined in a _panel options object_. `SimpleOptions` is an interface that describes the options object.
1. In `types.ts`, add a `CircleColor` type to hold the colors the users can choose from:
```
type CircleColor = 'red' | 'green' | 'blue';
```
1. In the `SimpleOptions` interface, add a new option called `color`:
```
color: CircleColor;
```
Here's the updated options definition:
**src/types.ts**
```ts
type SeriesSize = 'sm' | 'md' | 'lg';
type CircleColor = 'red' | 'green' | 'blue';
// interface defining panel options type
export interface SimpleOptions {
text: string;
showSeriesCount: boolean;
seriesCountSize: SeriesSize;
color: CircleColor;
}
```
#### Add an option control
To change the option from the panel editor, you need to bind the `color` option to an _option control_.
Grafana supports a range of option controls, such as text inputs, switches, and radio groups.
Let's create a radio control and bind it to the `color` option.
1. In `src/module.ts`, add the control at the end of the builder:
```ts
.addRadio({
path: 'color',
name: 'Circle color',
defaultValue: 'red',
settings: {
options: [
{
value: 'red',
label: 'Red',
},
{
value: 'green',
label: 'Green',
},
{
value: 'blue',
label: 'Blue',
},
],
}
});
```
The `path` is used to bind the control to an option. You can bind a control to nested option by specifying the full path within a options object, for example `colors.background`.
Grafana builds an options editor for you and displays it in the panel editor sidebar in the **Display** section.
#### Use the new option
You're almost done. You've added a new option and a corresponding control to change the value. But the plugin isn't using the option yet. Let's change that.
1. To convert option value to the colors used by the current theme, add a `switch` statement right before the `return` statement in `SimplePanel.tsx`.
**src/SimplePanel.tsx**
```ts
let color: string;
switch (options.color) {
case 'red':
color = theme.palette.redBase;
break;
case 'green':
color = theme.palette.greenBase;
break;
case 'blue':
color = theme.palette.blue95;
break;
}
```
1. Configure the circle to use the color.
```ts
<g>
<circle style={{ fill: color }} r={100} />
</g>
```
Now, when you change the color in the panel editor, the fill color of the circle changes as well.
## Create dynamic panels using data frames
Most panels visualize dynamic data from a Grafana data source. In this step, you'll create one circle per series, each with a radius equal to the last value in the series.
> To use data from queries in your panel, you need to set up a data source. If you don't have one available, you can use the [TestData](/docs/grafana/latest/features/datasources/testdata) data source while developing.
The results from a data source query within your panel are available in the `data` property inside your panel component.
```ts
const { data } = props;
```
`data.series` contains the series returned from a data source query. Each series is represented as a data structure called _data frame_. A data frame resembles a table, where data is stored by columns, or _fields_, instead of rows. Every value in a field share the same data type, such as string, number, or time.
Here's an example of a data frame with a time field, `Time`, and a number field, `Value`:
| Time | Value |
| ------------- | ----- |
| 1589189388597 | 32.4 |
| 1589189406480 | 27.2 |
| 1589189513721 | 15.0 |
Let's see how you can retrieve data from a data frame and use it in your visualization.
1. Get the last value of each field of type `number`, by adding the following to `SimplePanel.tsx`, before the `return` statement:
```ts
const radii = data.series
.map((series) => series.fields.find((field) => field.type === 'number'))
.map((field) => field?.values.get(field.values.length - 1));
```
`radii` will contain the last values in each of the series that are returned from a data source query. You'll use these to set the radius for each circle.
1. Change the `svg` element to the following:
```ts
<svg
className={styles.svg}
width={width}
height={height}
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
viewBox={`0 -${height / 2} ${width} ${height}`}
>
<g fill={color}>
{radii.map((radius, index) => {
const step = width / radii.length;
return <circle r={radius} transform={`translate(${index * step + step / 2}, 0)`} />;
})}
</g>
</svg>
```
Note how we're creating a `<circle>` element for each value in `radii`:
```ts
{
radii.map((radius, index) => {
const step = width / radii.length;
return <circle r={radius} transform={`translate(${index * step + step / 2}, 0)`} />;
});
}
```
We use the `transform` here to distribute the circle horizontally within the panel.
1. Rebuild your plugin and try it out by adding multiple queries to the panel. Refresh the dashboard.
If you want to know more about data frames, check out our introduction to [Data frames](/docs/grafana/latest/developers/plugins/data-frames/).
## Summary
In this tutorial you learned how to create a custom visualization for your dashboards.

View File

@ -1,5 +1,16 @@
---
title: Build a streaming data source plugin
aliases:
- ../../../plugins/build-a-streaming-data-source-plugin/
description: How to build a streaming data source plugin.
keywords:
- grafana
- plugins
- plugin
- streaming
- streaming data source
- datasource
weight: 600
---
# Build a streaming data source plugin
@ -8,7 +19,7 @@ In Grafana, you can set your dashboards to automatically refresh at a certain in
## Before you begin
This guide assumes that you're already familiar with how to [Build a data source plugin](/tutorials/build-a-data-source-plugin/).
This guide assumes that you're already familiar with how to [Build a data source plugin]({{< relref "./build-a-data-source-plugin" >}})
Grafana uses [RxJS](https://rxjs.dev/) to continuously send data from a data source to a panel visualization.

View File

@ -0,0 +1,207 @@
---
title: Build an app plugin
description: Learn at how to create an app for Grafana.
weight: 700
draft: true
keywords:
- grafana
- plugins
- plugin
- app
- app plugin
---
## Introduction
App plugins are Grafana plugins that can bundle data source and panel plugins within one package. They also let you create _custom pages_ within Grafana. Custom pages enable the plugin author to include things like documentation, sign-up forms, or to control other services over HTTP.
Data source and panel plugins will show up like normal plugins. The app pages will be available in the main menu.
{{% class "prerequisite-section" %}}
### Prerequisites
- Grafana 7.0
- NodeJS 12.x
- yarn
{{% /class %}}
## Set up your environment
{{< docs/shared lookup="tutorials/set-up-environment.md" source="grafana" version="latest" >}}
## Create a new plugin
{{< docs/shared lookup="tutorials/create-plugin.md" source="grafana" version="latest" >}}
## Anatomy of a plugin
{{< docs/shared lookup="tutorials/plugin-anatomy.md" source="grafana" version="latest" >}}
## App plugins
App plugins let you bundle resources such as dashboards, panels, and data sources into a single plugin.
Any resource you want to include needs to be added to the `includes` property in the `plugin.json` file. To add a resource to your app plugin, you need to include it to the `plugin.json`.
Plugins that are included in an app plugin are available like any other plugin.
Dashboards and pages can be added to the app menu by setting `addToNav` to `true`.
By setting `"defaultNav": true`, users can navigate to the dashboard by clicking the app icon in the side menu.
## Add a custom page
App plugins let you extend the Grafana user interface through the use of _custom pages_.
Any requests sent to `/a/<plugin-id>`, e.g. `/a/myorgid-simple-app/`, are routed to the _root page_ of the app plugin. The root page is a React component that returns the content for a given route.
While you're free to implement your own routing, in this tutorial you'll use a tab-based navigation page that you can use by calling `onNavChange`.
Let's add a tab for managing server instances.
1. In the `src/pages` directory, add a new file called `Instances.tsx`. This component contains the content for the new tab.
```ts
import { AppRootProps } from '@grafana/data';
import React from 'react';
export const Instances = ({ query, path, meta }: AppRootProps) => {
return <p>Hello</p>;
};
```
1. Register the page by adding it to the `pages` array in `src/pages/index.ts`.
**index.ts**
```ts
import { Instances } from './Instances';
```
```ts
{
component: Instances,
icon: 'file-alt',
id: 'instances',
text: 'Instances',
}
```
1. Add the page to the app menu, by including it in `plugin.json`. This will be the main view of the app, so we'll set `defaultNav` to let users quickly get to it by clicking the app icon in the side menu.
**plugin.json**
```json
"includes": [
{
"type": "page",
"name": "Instances",
"path": "/a/myorgid-simple-app?tab=instances",
"role": "Viewer",
"addToNav": true,
"defaultNav": true
}
]
```
> **Note:** While `page` includes typically reference pages created by the app, you can set `path` to any URL, internal or external. Try setting `path` to `https://grafana.com`.
## Configure the app
Let's add a new configuration page where users are able to configure default zone and regions for any instances they create.
1. In `module.ts`, add new configuration page using the `addConfigPage` method. `body` is the React component that renders the page content.
**module.ts**
```ts
.addConfigPage({
title: 'Defaults',
icon: 'fa fa-info',
body: DefaultsConfigPage,
id: 'defaults',
})
```
## Add a dashboard
#### Include a dashboard in your app
1. In `src/`, create a new directory called `dashboards`.
1. Create a file called `overview.json` in the `dashboards` directory.
1. Copy the JSON definition for the dashboard you want to include and paste it into `overview.json`. If you don't have one available, you can find a sample dashboard at the end of this step.
1. In `plugin.json`, add the following object to the `includes` property.
- The `name` of the dashboard needs to be the same as the `title` in the dashboard JSON model.
- `path` points out the file that contains the dashboard definition, relative to the `plugin.json` file.
```json
"includes": [
{
"type": "dashboard",
"name": "System overview",
"path": "dashboards/overview.json",
"addToNav": true
}
]
```
1. Save and restart Grafana to load the new changes.
## Bundle a plugin
An app plugin can contain panel and data source plugins that get installed along with the app plugin.
In this step, you'll add a data source to your app plugin. You can add panel plugins the same way by changing `datasource` to `panel`.
1. In `src/`, create a new directory called `datasources`.
1. Create a new data source using Grafana create-plugin tool in a temporary directory.
```bash
mkdir tmp
cd tmp
npx @grafana/create-plugin@latest
```
1. Move the `src` directory in the data source plugin to `src/datasources`, and rename it to `my-datasource`.
```bash
mv ./my-datasource/src ../src/datasources/my-datasource
```
Any bundled plugins are built along with the app plugin. Grafana looks for any subdirectory containing a `plugin.json` file and attempts to load a plugin in that directory.
To let users know that your plugin bundles other plugins, you can optionally display it on the plugin configuration page. This is not done automatically, so you need to add it to the `plugin.json`.
1. Include the data source in the `plugin.json`. The `name` property is only used for displaying in the Grafana UI.
```json
"includes": [
{
"type": "datasource",
"name": "My data source"
}
]
```
#### Include external plugins
If you want to let users know that your app requires an existing plugin, you can add it as a dependency in `plugin.json`. Note that they'll still need to install it themselves.
```json
"dependencies": {
"plugins": [
{
"type": "panel",
"name": "Worldmap Panel",
"id": "grafana-worldmap-panel",
"version": "^0.3.2"
}
]
}
```
## Summary
In this tutorial you learned how to create an app plugin.

View File

@ -1,14 +1,24 @@
---
title: Work with data frames
aliases:
- ../../../plugins/working-with-data-frames/
description: How to work with data frames.
keywords:
- grafana
- plugins
- plugin
- data frames
- dataframes
weight: 900
---
# Work with data frames
The [data frame]({{< relref "data-frames" >}}) is a columnar data structure that allows for efficient querying of large amounts of data. Since data frames are a central concept when developing plugins for Grafana, in this guide we'll look at some ways you can use them.
The [data frame]({{< relref "../../introduction-to-plugin-development/data-frames" >}}) is a columnar data structure that allows for efficient querying of large amounts of data. Since data frames are a central concept when developing plugins for Grafana, in this guide we'll look at some ways you can use them.
The `DataFrame` interface contains a `name` and an array of `fields` where each field contains the name, type, and the values for the field.
> **Note:** If you want to migrate an existing plugin to use the data frame format, refer to [Migrate to data frames]({{< relref "migration-guide/#migrate-to-data-frames" >}}).
> **Note:** If you want to migrate an existing plugin to use the data frame format, refer to [Migrate to data frames]({{< relref "../../migration-guide/v6.x-v7.x#migrate-to-data-frames" >}}).
## Create a data frame

View File

@ -0,0 +1,34 @@
---
title: Extend a Grafana plugin
menuTitle: Extend a plugin
keywords:
- grafana
- plugins
- plugin
- development
- extension
- documentation
description: An index of how-to topics for extending or enhancing Grafana plugins.
weight: 200
---
# Extend a Grafana plugin
This section contains how-to topics for extending or enhancing Grafana plugins:
- [Enable annotations]({{< relref "./add-support-for-annotations.md" >}})
- [Add anonymous usage reporting]({{< relref "./add-anonymous-usage-reporting.md" >}})
- [Add authentication for a data source plugin]({{< relref "./add-authentication-for-data-source-plugins.md" >}})
- [Add distributed tracing for backend plugins]({{< relref "./add-distributed-tracing-for-backend-plugins.md" >}})
- [Add features to Explore queries]({{< relref "./add-support-for-explore-queries.md" >}})
- [Add query editor help]({{< relref "./add-query-editor-help.md" >}})
- [Add support for variables]({{< relref "./add-support-for-variables.md" >}})
- [Build a custom panel option editor]({{< relref "./custom-panel-option-editors.md" >}})
- [Use extensions to add links to app plugins]({{< relref "./extend-the-grafana-ui-with-links.md" >}})
- [Work with cross-plugin links]({{< relref "./cross-plugin-linking.md" >}})
Additional resources:
- [Automate development with CI](https://grafana.github.io/plugin-tools/docs/ci)
- [Create nested plugins](https://grafana.github.io/plugin-tools/docs/nested-plugins)
- [Extend configurations](https://grafana.github.io/plugin-tools/docs/advanced-configuration)

View File

@ -1,10 +1,20 @@
---
title: Add anonymous usage reporting
aliases:
- ../../../plugins/add-anonymous-usage-reporting/
keywords:
- grafana
- plugins
- plugin
- anonymous usage
- reporting
description: How to add anonymous usage tracking to your Grafana plugin.
weight: 200
---
# Add anonymous usage reporting
Add anonymous usage tracking to your plugin to send [reporting events]({{< relref "../../setup-grafana/configure-grafana/#reporting_enabled" >}}) that describe how your plugin is being used to a tracking system configured by your Grafana server administrator.
Add anonymous usage tracking to your plugin to send [reporting events]({{< relref "../../../../setup-grafana/configure-grafana#reporting_enabled" >}}) that describe how your plugin is being used to a tracking system configured by your Grafana server administrator.
## Event reporting

View File

@ -1,8 +1,19 @@
---
title: Add authentication for data source plugins
aliases:
- ../../../plugins/add-authentication-for-data-source-plugins/
description: How to add authentication for data source plugins.
keywords:
- grafana
- plugins
- plugin
- authentication
- data source
- datasource
aliases:
- ../../plugins/developing/auth-for-datasources/
- /docs/grafana/next/developers/plugins/authentication/
title: Add authentication for data source plugins
weight: 300
---
# Add authentication for data source plugins
@ -30,7 +41,7 @@ Data source plugins have two ways of storing custom configuration: `jsonData` an
Users with the Viewer role can access data source configuration such as the contents of `jsonData` in cleartext. If you've enabled anonymous access, anyone who can access Grafana in their browser can see the contents of `jsonData`.
Users of [Grafana Enterprise](https://grafana.com/products/enterprise/grafana/) can restrict access to data sources to specific users and teams. For more information, refer to [Data source permissions](https://grafana.com/docs/grafana/latest/enterprise/datasource_permissions).
Users of [Grafana Enterprise](/products/enterprise/grafana/) can restrict access to data sources to specific users and teams. For more information, refer to [Data source permissions](/docs/grafana/latest/enterprise/datasource_permissions).
> **Important:** Do not use `jsonData` with sensitive data such as password, tokens, and API keys. If you need to store sensitive information, use `secureJsonData` instead.
@ -115,11 +126,11 @@ Once the user has saved the configuration for a data source, the secret data sou
The Grafana server comes with a proxy that lets you define templates for your requests: _proxy routes_. Grafana sends the proxy route to the server, decrypts the secrets along with other configuration, and adds them to the request before sending it.
> **Note:** Be sure not to confuse the data source proxy with the [auth proxy]({{< relref "../../setup-grafana/configure-security/configure-authentication/auth-proxy/" >}}). The data source proxy is used to authenticate a data source, while the auth proxy is used to log into Grafana itself.
> **Note:** Be sure not to confuse the data source proxy with the [auth proxy]({{< relref "../../../../setup-grafana/configure-security/configure-authentication/auth-proxy/index.md" >}}). The data source proxy is used to authenticate a data source, while the auth proxy is used to log into Grafana itself.
### Add a proxy route to your plugin
To forward requests through the Grafana proxy, you need to configure one or more _proxy routes_. A proxy route is a template for any outgoing request that is handled by the proxy. You can configure proxy routes in the [plugin.json](https://grafana.com/docs/grafana/latest/developers/plugins/metadata/) file.
To forward requests through the Grafana proxy, you need to configure one or more _proxy routes_. A proxy route is a template for any outgoing request that is handled by the proxy. You can configure proxy routes in the [plugin.json]({{< relref "../../metadata.md" >}}) file.
1. Add the route to `plugin.json`:
@ -284,7 +295,7 @@ While the data source proxy supports the most common authentication methods for
- Proxy routes only support HTTP or HTTPS.
- Proxy routes don't support custom token authentication.
If any of these limitations apply to your plugin, you need to add a [backend plugin]({{< relref "backend/" >}}). Because backend plugins run on the server, they can access decrypted secrets, which makes it easier to implement custom authentication methods.
If any of these limitations apply to your plugin, you need to add a [backend plugin]({{< relref "../../introduction-to-plugin-development/backend" >}}). Because backend plugins run on the server, they can access decrypted secrets, which makes it easier to implement custom authentication methods.
The decrypted secrets are available from the `DecryptedSecureJSONData` field in the instance settings.
@ -302,7 +313,7 @@ func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataReque
## Forward OAuth identity for the logged-in user
If your data source uses the same OAuth provider as Grafana itself, for example using [Generic OAuth Authentication]({{< relref "../../setup-grafana/configure-security/configure-authentication/generic-oauth/" >}}), then your data source plugin can reuse the access token for the logged-in Grafana user.
If your data source uses the same OAuth provider as Grafana itself, for example using [Generic OAuth Authentication]({{< relref "../../../../setup-grafana/configure-security/configure-authentication/generic-oauth" >}}), then your data source plugin can reuse the access token for the logged-in Grafana user.
To allow Grafana to pass the access token to the plugin, update the data source configuration and set the `jsonData.oauthPassThru` property to `true`. The [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) settings provide a toggle, the **Forward OAuth Identity** option, for this. You can also build an appropriate toggle to set `jsonData.oauthPassThru` in your data source configuration page UI.
@ -426,7 +437,7 @@ func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthR
## Forward user header for the logged-in user
When [send_user_header]({{< relref "../../setup-grafana/configure-grafana/_index.md#send_user_header" >}}) is enabled, Grafana passes the user header to the plugin using the `X-Grafana-User` header. You can forward this header as well as [authorization headers](#forward-oauth-identity-for-the-logged-in-user) or [configured cookies](#forward-cookies-for-the-logged-in-user).
When `send_user_header` is enabled, Grafana passes the user header to the plugin using the `X-Grafana-User` header. You can forward this header as well as [authorization headers](#forward-oauth-identity-for-the-logged-in-user) or [configured cookies](#forward-cookies-for-the-logged-in-user).
**`QueryData`**

View File

@ -1,5 +1,17 @@
---
title: Add distributed tracing for backend plugins
aliases:
- ../../../plugins/add-distributed-tracing-for-backend-plugins/
keywords:
- grafana
- plugins
- plugin
- distributed tracing
- tracing
- backend
- back-end
description: How to add distributed tracing for backend plugins.
weight: 350
---
# Add distributed tracing for backend plugins
@ -22,7 +34,7 @@ tracing = true
Grafana supports [OpenTelemetry](https://opentelemetry.io/) for distributed tracing. If Grafana is configured to use a deprecated tracing system (Jaeger or OpenTracing), then tracing is disabled in the plugin provided by the SDK and configured when calling `datasource.Manage | app.Manage`.
OpenTelemetry must be enabled and configured for the Grafana instance. Please refer to the [Grafana configuration documentation](
{{< relref "../../setup-grafana/configure-grafana/#tracingopentelemetry" >}}) for more information.
{{< relref "../../../../setup-grafana/configure-grafana#tracingopentelemetry" >}}) for more information.
Refer to the [OpenTelemetry Go SDK](https://pkg.go.dev/go.opentelemetry.io/otel) for in-depth documentation about all the features provided by OpenTelemetry.

View File

@ -1,5 +1,16 @@
---
title: Add query editor help
aliases:
- ../../../plugins/add-query-editor-help/
keywords:
- grafana
- plugins
- plugin
- queries
- query editor
- query editor help
description: How to add a help component to query editors in Grafana.
weight: 500
---
# Add query editor help

View File

@ -1,16 +1,26 @@
---
title: Add support for annotations
title: Enable annotations
menuTitle: Enable annotations
aliases:
- ../../../plugins/add-support-for-annotations/
description: Add support for annotations in your plugin.
keywords:
- grafana
- plugins
- plugin
- annotations
weight: 100
---
# Add support for annotations
# Enable annotations
You can add support to your plugin for annotations that will insert information into Grafana alerts. This guide explains how to add support for [annotations]({{< relref "../../dashboards/build-dashboards/annotate-visualizations/#querying-other-data-sources " >}}) to a data source plugin.
You can add support to your plugin for annotations that will insert information into Grafana alerts. This guide explains how to add support for [annotations]({{< relref "../../../../dashboards/build-dashboards/annotate-visualizations#querying-other-data-sources" >}}) to a data source plugin.
## Support annotations in your data source plugin
To enable annotations, simply add two lines of code to your plugin. Grafana uses your default query editor for editing annotation queries.
1. Add `"annotations": true` to the [plugin.json]({{< relref "metadata/" >}}) file to let Grafana know that your plugin supports annotations.
1. Add `"annotations": true` to the [plugin.json]({{< relref "../../metadata.md" >}}) file to let Grafana know that your plugin supports annotations.
**In `plugin.json`:**

View File

@ -1,10 +1,21 @@
---
title: Add features to Explore queries
aliases:
- ../../../plugins/add-support-for-explore-queries/
description: Add features to Explore queries.
keywords:
- grafana
- plugins
- plugin
- queries
- explore queries
- explore
weight: 400
---
# Add features for Explore queries
# Add features to Explore queries
[Explore]({{< relref "../../explore/" >}}) allows users can make ad-hoc queries without the use of a dashboard. This is useful when they want to troubleshoot or learn more about the data.
[Explore]({{< relref "../../../../explore" >}}) allows users can make ad-hoc queries without the use of a dashboard. This is useful when they want to troubleshoot or learn more about the data.
Your data source supports Explore by default and uses the existing query editor for the data source. This guide explains how to extend functionality for Explore queries in a data source plugin.

View File

@ -1,10 +1,20 @@
---
title: Add support for variables in plugins
title: Add support for variables
aliases:
- ../../../plugins/add-support-for-variables/
description: Add support for variables.
keywords:
- grafana
- plugins
- plugin
- queries
- variables
weight: 600
---
# Add support for variables in plugins
# Add support for variables
Variables are placeholders for values, and you can use them to create templated queries, and dashboard or panel links. For more information on variables, refer to [Templates and variables]({{< relref "../../dashboards/variables/" >}}).
Variables are placeholders for values, and you can use them to create templated queries, and dashboard or panel links. For more information on variables, refer to [Templates and variables]({{< relref "../../../../dashboards/variables" >}}).
In this guide, you'll see how you can turn a query string like this:
@ -58,7 +68,7 @@ For data sources, you need to use the `getTemplateSrv`, which returns an instanc
## Format multi-value variables
When a user selects multiple values for a variable, the value of the interpolated variable depends on the [variable format]({{< relref "../../dashboards/variables/variable-syntax/#advanced-variable-format-options" >}}).
When a user selects multiple values for a variable, the value of the interpolated variable depends on the [variable format]({{< relref "../../../../dashboards/variables/variable-syntax#advanced-variable-format-options" >}}).
A data source plugin can define the default format option when no format is specified by adding a third argument to the interpolation function.
@ -74,7 +84,7 @@ Now, when users write `$service`, the query looks like this:
SELECT * FROM services WHERE id IN (admin,auth,billing)
```
For more information on the available variable formats, refer to [Advanced variable format options]({{< relref "../../dashboards/variables/variable-syntax/#advanced-variable-format-options" >}}).
For more information on the available variable formats, refer to [Advanced variable format options]({{< relref "../../../../dashboards/variables/variable-syntax/index.md#advanced-variable-format-options" >}}).
## Set a variable from your plugin
@ -97,7 +107,7 @@ locationService.partial({ 'var-service': 'billing' }, true);
## Add support for query variables to your data source
A [query variable]({{< relref "../../dashboards/variables/add-template-variables/#add-a-query-variable" >}}) is a type of variable that allows you to query a data source for the values. By adding support for query variables to your data source plugin, users can create dynamic dashboards based on data from your data source.
A [query variable]({{< relref "../../../../dashboards/variables/add-template-variables#add-a-query-variable" >}}) is a type of variable that allows you to query a data source for the values. By adding support for query variables to your data source plugin, users can create dynamic dashboards based on data from your data source.
Let's start by defining a query model for the variable query:
@ -195,4 +205,4 @@ Let's create a custom query editor to allow the user to edit the query model.
.setVariableQueryEditor(VariableQueryEditor);
```
That's it! You can now try out the plugin by adding a [query variable]({{< relref "../../dashboards/variables/add-template-variables/#add-a-query-variable" >}}) to your dashboard.
That's it! You can now try out the plugin by adding a [query variable]({{< relref "../../../../dashboards/variables/add-template-variables#add-a-query-variable" >}}) to your dashboard.

View File

@ -1,6 +1,17 @@
---
title: Work with cross-plugin links
description: Learn how to add plugin links to a Grafana app plugin
aliases:
- ../../../plugins/cross-plugin-linking/
keywords:
- grafana
- plugins
- plugin
- links
- cross-plugin links
- extensions
- extensions api
description: Learn how to add plugin links to a Grafana app plugin.
weight: 800
---
# Work with cross-plugin links

View File

@ -1,5 +1,16 @@
---
title: Build a custom panel option editor
aliases:
- ../../../plugins/custom-panel-option-editors/
description: How to build a custom panel option editor.
keywords:
- grafana
- plugins
- plugin
- custom panel option editor
- customizing panel options
- panel options
weight: 700
---
# Build a custom panel option editor

View File

@ -1,6 +1,16 @@
---
title: Use extensions to add links to app plugins
aliases:
- ../../../plugins/extend-the-grafana-ui-with-links/
keywords:
- grafana
- plugins
- plugin
- links
- extensions
- app plugins
description: Learn how to add links to the Grafana user interface from an app plugin
weight: 760
---
# Use extensions to add links to app plugins
@ -12,7 +22,7 @@ You can use the Plugin extensions API with your Grafana app plugins to add links
Be sure your plugin meets the following requirements before proceeding:
- It must be an app plugin.
- It must be preloaded (by setting the [preload property]({{< relref "./metadata" >}}) to `true` in the `plugin.json`
- It must be preloaded (by setting the [preload property]({{< relref "../../metadata.md" >}}) to `true` in the `plugin.json`
- It must be installed and enabled.
## Available extension points within Grafana

View File

@ -1,12 +1,23 @@
---
description: Get started guide
title: Get started with plugins
title: Get started with Grafana plugin development
menuTitle: Get started with plugins
keywords:
- grafana
- plugins
- plugin
- documentation
description: Get started with Grafana plugin development.
weight: 200
---
# Get started with Grafana plugins
# Get started with Grafana plugin development
This section contains guidance for building plugins.
This section contains guidance for building plugins:
- [Develop with local Grafana]({{< relref "./development-with-local-grafana.md" >}})
Additional resources:
- [Get started with creating a plugin](https://grafana.github.io/plugin-tools/docs/getting-started)
- [Types of Grafana plugins](https://grafana.com/docs/grafana/latest/administration/plugin-management/)
- [Types of Grafana plugins](/docs/grafana/latest/administration/plugin-management/)
- [Set up your development environment](https://grafana.github.io/plugin-tools/docs/docker)

View File

@ -1,5 +1,15 @@
---
title: Develop with a local environment
aliases:
- ../../plugins/development-with-local-grafana/
description: How to develop with a local Grafana environment.
keywords:
- grafana
- plugins
- plugin
- development environment
- local environment
weight: 400
---
# Develop with a local environment

View File

@ -1,13 +1,21 @@
---
description: Conceptual topics for plugin development
title: Introduction to plugin development
title: Introduction to Grafana plugin development
menuTitle: Introduction to plugin development
keywords:
- grafana
- plugins
- plugin
- documentation
description: Conceptual topics for Grafana plugin development.
weight: 100
---
# Introduction to Grafana plugin development
This section contains topics related to the key concepts for Grafana plugin development.
This section contains documentation related to the key concepts for Grafana plugin development.
- [Backend plugins]({{< relref "../backend/" >}})
- [Grafana plugin SDK for Go]({{< relref "../backend/grafana-plugin-sdk-for-go.md" >}})
- [Plugin protocol]({{< relref "../backend/plugin-protocol.md" >}})
- [Data frames]({{< relref "data-frames.md">}})
- [Backend plugins]({{< relref "./backend" >}})
- [Grafana plugin SDK for Go]({{< relref "./backend/grafana-plugin-sdk-for-go.md" >}})
- [Plugin protocol]({{< relref "./backend/plugin-protocol.md" >}})
- [Data frames]({{< relref "./data-frames.md" >}})
- [Error handling]({{< relref "./error-handling.md" >}})

View File

@ -1,6 +1,8 @@
---
title: Backend plugins
aliases:
- ../../plugins/developing/backend-plugins-guide/
- ../../plugins/backend/
keywords:
- grafana
- plugins
@ -8,7 +10,7 @@ keywords:
- plugin
- backend-plugins
- documentation
title: Backend plugins
description: Learn about the Grafana plugin system for backend development of Grafana integrations.
---
# Backend plugins
@ -27,7 +29,7 @@ Since Grafana v7.0, we have supported server-side plugins that remove this limit
The following examples give some common use cases for backend plugins:
- Enable [Grafana Alerting]({{< relref "../../../alerting/" >}}) for data sources.
- Enable [Grafana Alerting]({{< relref "../../../../alerting" >}}) for data sources.
- Connect to SQL database servers and other non-HTTP services that normally can't be connected to from a browser.
- Keep state between users, for example, by query caching for data sources.
- Use custom authentication methods and/or authorization checks that aren't supported in Grafana.
@ -57,7 +59,7 @@ Grafana's backend plugin system exposes several key capabilities, or building bl
#### Query data
The query data capability allows a backend plugin to handle data source queries that are submitted from a [dashboard]({{< relref "../../../dashboards/" >}}), [Explore]({{< relref "../../../explore/" >}}) or [Grafana Alerting]({{< relref "../../../alerting/" >}}). The response contains [data frames]({{< relref "../data-frames/" >}}), which are used to visualize metrics, logs, and traces.
The query data capability allows a backend plugin to handle data source queries that are submitted from a [dashboard]({{< relref "../../../../dashboards" >}}), [Explore]({{< relref "../../../../explore" >}}) or [Grafana Alerting]({{< relref "../../../../alerting" >}}). The response contains [data frames]({{< relref "../data-frames.md" >}}), which are used to visualize metrics, logs, and traces.
{{% admonition type="note" %}} Backend data source plugins are required to implement the query data capability.{{%
/admonition %}}
@ -72,7 +74,7 @@ Compared to the query data capability, where the response contains data frames,
Examples of use cases for implementing resources:
- Implement a custom data source proxy to provide certain authentication, authorization, or other requirements that are not supported in Grafana's [built-in data proxy]({{< relref "../../http_api/data_source/#data-source-proxy-calls" >}}).
- Implement a custom data source proxy to provide certain authentication, authorization, or other requirements that are not supported in Grafana's [built-in data proxy]({{< relref "../../../http_api/data_source#data-source-proxy-calls" >}}).
- Return data or information in a format suitable for use within a data source query editor to provide auto-complete functionality.
- Return static resources such as images or files.
- Send a command to a device, such as a microcontroller or IoT device.
@ -88,10 +90,10 @@ A plugin's health check endpoint is exposed in the Grafana HTTP API and allows e
#### Collect metrics
A backend plugin can collect and return runtime, process, and custom metrics using the text-based Prometheus [exposition format](https://prometheus.io/docs/instrumenting/exposition_formats/). If you're using the [Grafana Plugin SDK for Go]({{< relref "grafana-plugin-sdk-for-go/" >}}) to implement your backend plugin, then the [Prometheus instrumentation library for Go applications](https://github.com/prometheus/client_golang) is built-in. This SDK gives you Go runtime metrics and process metrics out of the box. You can use the [Prometheus instrumentation library](https://github.com/prometheus/client_golang) to add custom metrics to instrument your backend plugin.
A backend plugin can collect and return runtime, process, and custom metrics using the text-based Prometheus [exposition format](https://prometheus.io/docs/instrumenting/exposition_formats/). If you're using the [Grafana Plugin SDK for Go]({{< relref "./grafana-plugin-sdk-for-go.md" >}}) to implement your backend plugin, then the [Prometheus instrumentation library for Go applications](https://github.com/prometheus/client_golang) is built-in. This SDK gives you Go runtime metrics and process metrics out of the box. You can use the [Prometheus instrumentation library](https://github.com/prometheus/client_golang) to add custom metrics to instrument your backend plugin.
The Grafana HTTP API offers an endpoint (`/api/plugins/<plugin id>/metrics`) that allows you to configure a Prometheus instance to scrape the metrics.
#### Streaming
The streaming capability allows a backend plugin to handle data source queries that are streaming. For more information, refer to [Build a streaming data source plugin]({{<relref "../build-a-streaming-data-source-plugin.md">}})
The streaming capability allows a backend plugin to handle data source queries that are streaming. For more information, refer to [Build a streaming data source plugin]({{< relref "../../create-a-grafana-plugin/develop-a-plugin/build-a-streaming-data-source-plugin" >}}).

View File

@ -1,4 +1,7 @@
---
title: Grafana plugin SDK for Go
aliases:
- ../../plugins/backend/grafana-plugin-sdk-for-go/
keywords:
- grafana
- plugins
@ -7,18 +10,18 @@ keywords:
- backend-plugins
- sdk
- documentation
title: Grafana Plugin SDK for Go
description: Learn about the Grafana plugin SDK for Go, a Go module with packages for implementing a Grafana backend plugin.
---
# Grafana plugin SDK for Go
The [Grafana plugin SDK for Go](https://pkg.go.dev/mod/github.com/grafana/grafana-plugin-sdk-go?tab=overview) is a [Go](https://golang.org/) module that provides a set of [packages](https://pkg.go.dev/mod/github.com/grafana/grafana-plugin-sdk-go?tab=packages) that you can use to implement a backend plugin.
The plugin SDK provides a high-level framework with APIs, utilities, and tooling. By using the SDK, you can avoid the need to learn the details of the [plugin protocol]({{< relref "plugin-protocol/" >}}) and RPC communication protocol, so you don't have to manage either one.
The plugin SDK provides a high-level framework with APIs, utilities, and tooling. By using the SDK, you can avoid the need to learn the details of the [plugin protocol]({{< relref "./plugin-protocol.md" >}}) and RPC communication protocol, so you don't have to manage either one.
## Versioning
The Grafana plugin Go SDK is still in development. It is based on the [plugin protocol]({{< relref "plugin-protocol/" >}}), which is versioned separately and is considered stable. However, from time to time, we might introduce breaking changes in the SDK.
The Grafana plugin Go SDK is still in development. It is based on the [plugin protocol]({{< relref "./plugin-protocol" >}}), which is versioned separately and is considered stable. However, from time to time, we might introduce breaking changes in the SDK.
When we update the plugin SDK, those plugins that use an older version of the SDK should still work with Grafana. However, these older plugins may be unable to use the new features and capabilities we introduce in updated SDK versions.

View File

@ -1,4 +1,7 @@
---
title: Plugin protocol
aliases:
- ../../plugins/backend/plugin-protocol/
keywords:
- grafana
- plugins
@ -6,7 +9,7 @@ keywords:
- plugin
- backend-plugins
- documentation
title: Plugin protocol
description: Learn about the Grafana wire protocol used for communication between the Grafana server and backend plugins.
---
# Plugin protocol
@ -15,7 +18,7 @@ The Grafana server uses a physical wire protocol to communicate with backend plu
## Developing with the plugin protocol
{{% admonition type="caution" %}} We strongly recommend that backend plugin development not be implemented directly against the protocol. Instead, we prefer that you use the [Grafana Plugin SDK for Go]({{< relref "grafana-plugin-sdk-for-go/" >}}) that implements this protocol and provides higher-level APIs. {{%
{{% admonition type="caution" %}} We strongly recommend that backend plugin development not be implemented directly against the protocol. Instead, we prefer that you use the [Grafana Plugin SDK for Go]({{< relref "./grafana-plugin-sdk-for-go" >}}) that implements this protocol and provides higher-level APIs. {{%
/admonition %}}
If you choose to develop against the plugin protocol directly, you can do so using [Protocol Buffers](https://developers.google.com/protocol-buffers) (that is, protobufs) with [gRPC](https://grpc.io/).
@ -23,7 +26,7 @@ If you choose to develop against the plugin protocol directly, you can do so usi
Grafana's plugin protocol protobufs are available in the [GitHub repository](https://github.com/grafana/grafana-plugin-sdk-go/blob/master/proto/backend.proto).
{{% admonition type="note" %}}
The plugin protocol lives in the [Grafana Plugin SDK for Go]({{< relref "grafana-plugin-sdk-for-go/" >}}) because Grafana itself uses parts of the SDK as a dependency.
The plugin protocol lives in the [Grafana Plugin SDK for Go]({{< relref "./grafana-plugin-sdk-for-go.md" >}}) because Grafana itself uses parts of the SDK as a dependency.
{{% /admonition %}}
## Versioning

View File

@ -1,5 +1,14 @@
---
title: Data frames
aliases:
- ../../plugins/data-frames/
description: Learn about data frames and how they work in plugins.
keywords:
- grafana
- plugins
- plugin
- data frames
- dataframes
---
# Data frames
@ -8,11 +17,11 @@ Grafana supports a variety of different data sources, each with its own data mod
The data frame structure is a concept that's borrowed from data analysis tools like the [R programming language](https://www.r-project.org) and [Pandas](https://pandas.pydata.org/).
> Data frames are available in Grafana 7.0+, and replaced the Time series and Table structures with a more generic data structure that can support a wider range of data types.
> **Note:** Data frames are available in Grafana 7.0+, and replaced the Time series and Table structures with a more generic data structure that can support a wider range of data types.
This document gives an overview of the data frame structure, and of how data is handled within Grafana.
### Data frame fields
## Data frame fields
A data frame is a collection of _fields_, where each field corresponds to a column. Each field, in turn, consists of a collection of values and metadata, such as the data type of those values.
@ -76,7 +85,7 @@ Each field has three values, and each value in a field must share the same type.
One restriction on data frames is that all fields in the frame must be of the same length to be a valid data frame.
### Field configurations
## Field configurations
Each field in a data frame contains optional information about the values in the field, such as units, scaling, and so on.
@ -88,13 +97,13 @@ We have seen how field configs contain type information, and they also have anot
A data transformation is any function that accepts a data frame as input, and returns another data frame as output. By using data frames in your plugin, you get a range of transformations for free.
To learn more about data transformations in Grafana, refer to [Transform data](https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/transform-data/).
To learn more about data transformations in Grafana, refer to [Transform data]({{< relref "../../../panels-visualizations/query-transform-data/transform-data" >}}).
## Data frames as time series
A data frame with at least one time field is considered a _time series_.
For more information on time series, refer to our [Introduction to time series]({{< relref "../../fundamentals/timeseries/" >}}).
For more information on time series, refer to our [Introduction to time series]({{< relref "../../../fundamentals/timeseries" >}}).
### Wide format
@ -183,7 +192,7 @@ Dimensions: 5 fields by 2 rows
+---------------------+------------------+------------------+------------------+------------------+
```
> **Note:** Not all panels support the wide time series data frame format. To keep full backward compatibility Grafana has introduced a transformation that you can use to convert from the wide to the long format. For usage information, refer to the [Prepare time series-transformation]({{< relref "../../panels-visualizations/query-transform-data/transform-data/#prepare-time-series" >}}).
> **Note:** Not all panels support the wide time series data frame format. To keep full backward compatibility Grafana has introduced a transformation that you can use to convert from the wide to the long format. For usage information, refer to the [Prepare time series-transformation]({{< relref "../../../panels-visualizations/query-transform-data/transform-data#prepare-time-series" >}}).
## Technical references

View File

@ -1,5 +1,14 @@
---
title: Work with error handling
aliases:
- ../../plugins/error-handling/
description: How to handle errors in plugins.
keywords:
- grafana
- plugins
- plugin
- errors
- error handling
---
# Work with error handling
@ -44,7 +53,7 @@ try {
}
```
> **Note:** Grafana displays the exception message in the UI as written, so use grammatically correct sentences. For more information, refer to the [Documentation style guide](https://github.com/grafana/grafana/blob/main/contribute/style-guides/documentation-style-guide.md).
> **Note:** Grafana displays the exception message in the UI as written, so use grammatically correct sentences. For more information, refer to the [Documentation style guide](/docs/writers-toolkit/).
## Common error scenarios

View File

@ -1,18 +1,20 @@
---
title: Work with legacy plugins
aliases:
- ../../plugins/development/
- /docs/grafana/next/plugins/apps/
- /docs/grafana/next/plugins/datasources/
- /docs/grafana/next/plugins/developing/development/
- /docs/grafana/next/plugins/panels/
title: Legacy plugins
description: Deprecated guide for Angular plugin development.
weight: 600
---
# Legacy plugins
# Work with legacy plugins
> **Note:** Since Grafana 7.0, writing plugins using Angular is no longer recommended. If you're looking to build a new plugin, refer to [Plugins]({{< relref "../" >}}).
> **Note:** Since Grafana 7.0, writing plugins using Angular is no longer recommended. If you're looking to build a new plugin, refer to our [Plugins]({{< relref "../../plugins" >}}) documentation.
You can extend Grafana by writing your own plugins and then share them with other users in [our plugin repository](https://grafana.com/plugins).
You can extend Grafana by writing your own plugins and then share them with other users in [our plugin repository](/plugins/).
Grafana already has a strong community of contributors and plugin developers. By making it easier to develop and install plugins with resources such as this guide, we hope that the community can grow even stronger and develop new plugins that we would never think about.
@ -32,7 +34,7 @@ Example plugins
You might also be interested in the available tutorials around authoring a plugin.
- [Grafana Tutorials](https://grafana.com/tutorials/)
- [Grafana Tutorials]({{< relref "../create-a-grafana-plugin/develop-a-plugin" >}})
## What languages?
@ -40,29 +42,29 @@ Since everything turns into JavaScript, it's up to you to choose which language
## Buildscript
You can use any build system that supports systemjs. All the built content should end up in a folder named `dist` and be committed to the repository. By committing the dist folder, the person who installs your plugin does not have to run any build script. All of our example plugins have a build script configured.
You can use any build system that supports `systemjs`. All the built content should end up in a folder named `dist` and be committed to the repository. By committing the dist folder, the person who installs your plugin does not have to run any build script. All of our example plugins have a build script configured.
## Keep your plugin up to date
New versions of Grafana can sometimes cause plugins to break. See our [documentation](https://grafana.com/docs/grafana/latest/developers/plugins/migration-guide/) for changes in
New versions of Grafana can sometimes cause plugins to break. See our [documentation]({{< relref "../migration-guide" >}}) for changes in
Grafana that can impact your plugin.
## Metadata
See the [coding styleguide]({{< relref "style-guide/" >}}) for details on the metadata.
See the [coding styleguide]({{< relref "./style-guide.md" >}}) for details on the metadata.
## module.(js|ts)
This is the entry point for every plugin. This is the place where you should export
your plugin implementation. Depending on what kind of plugin you are developing you
will be expected to export different things. You can find what's expected for [datasource]({{< relref "data-sources/" >}}), [panels]({{< relref "panels/" >}})
and [apps]({{< relref "apps/" >}}) plugins in the documentation.
will be expected to export different things. You can find what's expected for [datasource]({{< relref "./data-sources.md" >}}), [panels]({{< relref "./panels.md" >}})
and [apps]({{< relref "./apps.md" >}}) plugins in the documentation.
The Grafana SDK is quite small so far and can be found here:
- [SDK file in Grafana](https://github.com/grafana/grafana/blob/main/public/app/plugins/sdk.ts)
The SDK contains three different plugin classes: PanelCtrl, MetricsPanelCtrl and QueryCtrl. For plugins of the panel type, the module.js file should export one of these. There are some extra classes for [data sources]({{< relref "data-sources/" >}}).
The SDK contains three different plugin classes: PanelCtrl, MetricsPanelCtrl and QueryCtrl. For plugins of the panel type, the module.js file should export one of these. There are some extra classes for [data sources]({{< relref "./data-sources.md" >}}).
Example:
@ -91,7 +93,7 @@ export { WorldmapCtrl as PanelCtrl };
There are three ways that you can start developing a Grafana plugin.
1. Set up a Grafana development environment. [(described here)](https://github.com/grafana/grafana/blob/main/contribute/developer-guide.md) and place your plugin in the `data/plugins` folder.
1. Install Grafana and place your plugin in the plugins directory which is set in your [config file](/administration/configuration). By default this is `/var/lib/grafana/plugins` on Linux systems.
1. Install Grafana and place your plugin in the plugins directory which is set in your config file. By default this is `/var/lib/grafana/plugins` on Linux systems.
1. Place your plugin directory anywhere you like and specify it grafana.ini.
We encourage people to set up the full Grafana environment so that you can get inspiration from the rest of the Grafana code base.
@ -110,7 +112,7 @@ There are a number of Grafana events that a plugin can hook into:
- `data-snapshot-load` is an event triggered to load data when in snapshot mode.
- `data-error` is used to handle errors on dashboard refresh.
If a panel receives data and hooks into the `data-received` event then it should handle snapshot mode too. Otherwise the panel will not work if saved as a snapshot. [Getting Plugins to work in Snapshot Mode]({{< relref "snapshot-mode/" >}}) describes how to add support for this.
If a panel receives data and hooks into the `data-received` event then it should handle snapshot mode too. Otherwise the panel will not work if saved as a snapshot. [Getting Plugins to work in Snapshot Mode]({{< relref "./snapshot-mode" >}}) describes how to add support for this.
## Examples
@ -124,9 +126,9 @@ We have three different examples that you can fork/download to get started devel
## Other Articles
- [Getting Plugins to work in Snapshot Mode]({{< relref "snapshot-mode/" >}})
- [Plugin Defaults and Editor Mode]({{< relref "defaults-and-editor-mode/" >}})
- [Grafana Plugin Code Styleguide]({{< relref "style-guide/" >}})
- [Grafana Apps]({{< relref "apps/" >}})
- [Grafana Data Sources]({{< relref "data-sources/" >}})
- [plugin.json Schema]({{< relref "../metadata/" >}})
- [Getting Plugins to work in Snapshot Mode]({{< relref "./snapshot-mode.md" >}})
- [Plugin Defaults and Editor Mode]({{< relref "./defaults-and-editor-mode.md" >}})
- [Grafana Plugin Code Styleguide]({{< relref "./style-guide.md" >}})
- [Grafana Apps]({{< relref "./apps.md" >}})
- [Grafana Data Sources]({{< relref "./data-sources.md" >}})
- [plugin.json Schema]({{< relref "../metadata.md" >}})

View File

@ -1,11 +1,12 @@
---
title: Legacy app plugins
aliases:
- ../../../plugins/developing/apps/
keywords:
- grafana
- plugins
- documentation
title: Legacy app plugins
description: Deprecated guide for Angular plugin development.
---
# Legacy app plugins

View File

@ -1,11 +1,12 @@
---
title: Legacy data source plugins
aliases:
- ../../../plugins/developing/datasources/
keywords:
- grafana
- plugins
- documentation
title: Legacy data source plugins
description: Deprecated guide for Angular plugin development.
---
# Legacy data source plugins

View File

@ -1,7 +1,8 @@
---
title: Legacy defaults and editor mode
aliases:
- ../../../plugins/developing/defaults-and-editor-mode/
title: Legacy defaults and editor mode
description: Deprecated guide for Angular plugin development.
---
# Legacy defaults and editor mode

View File

@ -1,4 +1,5 @@
---
title: Legacy panel plugins
aliases:
- ../../../plugins/developing/panels/
keywords:
@ -6,7 +7,7 @@ keywords:
- plugins
- panel
- documentation
title: Legacy panel plugins
description: Deprecated guide for Angular plugin development.
---
# Legacy panel plugins

View File

@ -1,7 +1,8 @@
---
title: Legacy review guidelines
aliases:
- ../../../plugins/developing/plugin-review-guidelines/
title: Legacy review guidelines
description: Deprecated guide for Angular plugin development.
---
# Legacy review guidelines
@ -10,7 +11,7 @@ The Grafana team reviews all plugins that are published on Grafana.com. There ar
## Metadata
The plugin metadata consists of a `plugin.json` file and the README.md file. The `plugin.json` file is used by Grafana to load the plugin, and the README.md file is shown in the plugins section of Grafana and the plugins section of https://grafana.com.
The plugin metadata consists of a `plugin.json` file and the README.md file. The `plugin.json` file is used by Grafana to load the plugin, and the README.md file is shown in the [plugins catalog](/plugins).
### README.md
@ -161,7 +162,7 @@ For more information about data sources, refer to the [basic guide for data sour
If possible, any passwords or secrets should be saved in the `secureJsonData` blob. To encrypt sensitive data, the Grafana server's proxy feature must be used. The Grafana server has support for token authentication (OAuth) and HTTP Header authentication. If the calls have to be sent directly from the browser to a third-party API, this will not be possible and sensitive data will not be encrypted.
Read more here about how [authentication for data sources]({{< relref "../add-authentication-for-data-source-plugins/" >}}) works.
Read more here about how [authentication for data sources]({{< relref "../create-a-grafana-plugin/extend-a-plugin/add-authentication-for-data-source-plugins" >}}) works.
If using the proxy feature, the Configuration page should use the `secureJsonData` blob like this:

View File

@ -1,7 +1,8 @@
---
title: Legacy snapshot mode
aliases:
- ../../../plugins/developing/snapshot-mode/
title: Legacy snapshot mode
description: Deprecated guide for Angular plugin development.
---
# Legacy snapshot mode

View File

@ -1,7 +1,8 @@
---
title: Legacy code style guide
aliases:
- ../../../plugins/developing/code-styleguide/
title: Legacy code style guide
description: Deprecated guide for Angular plugin development.
---
# Legacy code style guide
@ -27,7 +28,7 @@ grafana-piechart-panel
mtanda-histogram-panel
```
For more information about the file format for `plugin.json` file, refer to [metadata]({{< relref "../metadata/" >}}).
For more information about the file format for `plugin.json` file, refer to [metadata]({{< relref "../metadata.md" >}}).
Minimal plugin.json:

View File

@ -5,7 +5,10 @@ keywords:
- grafana
- plugins
- documentation
description: Reference for the plugin.json metadata file.
title: plugin.json
menuTitle: Reference (plugin.json)
weight: 700
---
# plugin.json
@ -34,7 +37,7 @@ The plugin.json file is required for all plugins. When Grafana starts, it scans
| `metrics` | boolean | No | For data source plugins, if the plugin supports metric queries. Used to enable the plugin in the panel editor. |
| `preload` | boolean | No | Initialize plugin on startup. By default, the plugin initializes on first use. Useful for app plugins that should load without user interaction. |
| `queryOptions` | [object](#queryoptions) | No | For data source plugins. There is a query options section in the plugin's query editor and these options can be turned on if needed. |
| `routes` | [object](#routes)[] | No | For data source plugins. Proxy routes used for plugin authentication and adding headers to HTTP requests made by the plugin. For more information, refer to [Authentication for data source plugins](https://grafana.com/docs/grafana/latest/developers/plugins/authentication/). |
| `routes` | [object](#routes)[] | No | For data source plugins. Proxy routes used for plugin authentication and adding headers to HTTP requests made by the plugin. For more information, refer to [Authentication for data source plugins]({{< relref "./create-a-grafana-plugin/extend-a-plugin/add-authentication-for-data-source-plugins" >}}). |
| `skipDataQuery` | boolean | No | For panel plugins. Hides the query editor. |
| `state` | string | No | Marks a plugin as a pre-release. Possible values are: `alpha`, `beta`. |
| `streaming` | boolean | No | For data source plugins, if the plugin supports streaming. Used in Explore to start live streaming. |
@ -179,7 +182,7 @@ For data source plugins. There is a query options section in the plugin's query
## routes
For data source plugins. Proxy routes used for plugin authentication and adding headers to HTTP requests made by the plugin. For more information, refer to [Authentication for data source plugins](https://grafana.com/docs/grafana/latest/developers/plugins/authentication/).
For data source plugins. Proxy routes used for plugin authentication and adding headers to HTTP requests made by the plugin. For more information, refer to [Authentication for data source plugins]({{< relref "./create-a-grafana-plugin/extend-a-plugin/add-authentication-for-data-source-plugins" >}}).
### Properties

View File

@ -1,13 +1,15 @@
---
title: Migrate a plugin
aliases:
- ../../plugins/developing/migration-guide
description: A guide for migrating and updating a Grafana plugin.
keywords:
- grafana
- plugins
- migration
- plugin
- documentation
title: Migration guides
weight: 500
---
<script>
@ -34,7 +36,7 @@ title: Migration guides
})();
</script>
# Plugin migration guide
# Migrate a plugin
The following guides help you identify the steps required to update a plugin following changes between versions of Grafana.

View File

@ -1,13 +1,13 @@
---
description: Guide for migrating plugins from AngularJS to React
title: Migrate a plugin from AngularJS to React
menuTitle: Angular to React
description: Guide for migrating plugins from AngularJS to React.
keywords:
- grafana
- plugins
- migration
- plugin
- documentation
title: Migrate plugins from AngularJS to React
menutitle: Angular to React
weight: 1000
---

View File

@ -1,4 +1,6 @@
---
title: Migrate plugins from Grafana version 6.x to 7.0
menuTitle: v6.x to v7.x
description: Guide for migrating plugins from Grafana v6.x to v7.x
keywords:
- grafana
@ -6,8 +8,6 @@ keywords:
- migration
- plugin
- documentation
title: Migrate plugins from Grafana version 6.x to 7.x
menutitle: v6.x to v7.x
weight: 2500
---
@ -23,7 +23,7 @@ Plugins built using Angular still work in the near term, but we strongly encoura
### New data format
Along with the move to React, the new plugin platform introduced a new internal data format called [data frames](data-frames.md).
Along with the move to React, the new plugin platform introduced a new internal data format called [data frames]({{< relref "../../introduction-to-plugin-development/data-frames" >}}).
Previously, data source plugins could send data either as time series or tables. With data frames, data sources can send any data in a table-like structure. This gives you more flexibility to visualize your data in Grafana.
@ -78,7 +78,7 @@ async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
## Troubleshoot plugin migration
As of Grafana 7.0, backend plugins can now be cryptographically signed to verify their origin. By default, Grafana ignores unsigned plugins. For more information, refer to [Allow unsigned plugins]({{< relref "../../../../administration/plugin-management/#allow-unsigned-plugins" >}}).
As of Grafana 7.0, backend plugins can now be cryptographically signed to verify their origin. By default, Grafana ignores unsigned plugins. For more information, refer to [Allow unsigned plugins]({{< relref "../../../../administration/plugin-management#allow-unsigned-plugins" >}}).
## From version 6.5.x to 7.3.0

View File

@ -1,13 +1,13 @@
---
description: Guide for migrating plugins from Grafana v7.x to v8.x
title: Migrate plugins from Grafana version 7.x.x to 8.x.x
menuTitle: v7.x to v8.x
description: Guide for migrating plugins from Grafana v7.x to v8.x.
keywords:
- grafana
- plugins
- migration
- plugin
- documentation
title: Migrate plugins from Grafana version 7.x to 8.x
menutitle: v7.x to v8.x
weight: 2400
---
@ -154,9 +154,9 @@ func (d *SampleDatasource) CheckHealth(_ context.Context, req *backend.CheckHeal
We strongly recommend that you not allow unsigned plugins in your Grafana installation. By allowing unsigned plugins, we can't guarantee the authenticity of the plugin, which could compromise the security of your Grafana installation.
To sign your plugin, see [Sign a plugin](https://grafana.com/docs/grafana/latest/developers/plugins/sign-a-plugin/#sign-a-plugin).
To sign your plugin, see [Sign a plugin]({{< relref "../../publish-a-plugin/sign-a-plugin.md" >}}).
You can still run and develop an unsigned plugin by running your Grafana instance in [development mode](https://grafana.com/docs/grafana/latest/administration/configuration/#app_mode). Alternatively, you can use the [allow_loading_unsigned_plugins]({{< relref "../../../../setup-grafana/configure-grafana/#allow_loading_unsigned_plugins" >}}) configuration setting.
You can still run and develop an unsigned plugin by running your Grafana instance in [development mode](/docs/grafana/latest/administration/configuration/#app_mode). Alternatively, you can use the [allow_loading_unsigned_plugins]({{< relref "../../../../setup-grafana/configure-grafana#allow_loading_unsigned_plugins" >}}) configuration setting.
## Update react-hook-form from v6 to v7
@ -198,7 +198,7 @@ import { cx, css } from '@emotion/css';
## Update needed for app plugins using dashboards
To make side navigation work properly - app plugins targeting Grafana `8.+` and integrating into the side menu via [addToNav]({{< relref "../../metadata/#properties-4" >}}) property need to adjust their `plugin.json` and all dashboard json files to have a matching `uid`.
To make side navigation work properly - app plugins targeting Grafana `8.+` and integrating into the side menu via [addToNav]({{< relref "../../metadata#properties-4" >}}) property need to adjust their `plugin.json` and all dashboard json files to have a matching `uid`.
**`plugin.json`**

View File

@ -1,4 +1,6 @@
---
title: Migrate plugins from Grafana version 8.3.x to 8.4.x
menuTitle: v8.3.x to v8.4.x
description: Guide for migrating plugins from Grafana v8.3.x to v8.4.x
keywords:
- grafana
@ -6,8 +8,6 @@ keywords:
- migration
- plugin
- documentation
title: Migrate plugins from Grafana version 8.3.x to 8.4.x
menutitle: v8.3.x to v8.4.x
weight: 2200
---

View File

@ -1,4 +1,6 @@
---
title: Migrate plugins from Grafana version 8.x to 9.x
menuTitle: v8.x to v9.x
description: Guide for migrating plugins from Grafana v8.x to v9.x
keywords:
- grafana
@ -6,8 +8,6 @@ keywords:
- migration
- plugin
- documentation
title: Migrate plugins from Grafana version 8.x to 9.x
menutitle: v8.x to v9.x
weight: 2300
---
@ -73,7 +73,7 @@ We have removed the deprecated `getFormStyles` function from [grafana-ui](https:
### `/api/ds/query` replaces `/api/tsdb/query`
We have removed the deprecated `/api/tsdb/query` metrics endpoint. Use [/api/ds/query]({{< relref "../../../http_api/data_source/#query-a-data-source" >}}) instead.
We have removed the deprecated `/api/tsdb/query` metrics endpoint. Use [/api/ds/query]({{< relref "../../../http_api/data_source#query-a-data-source" >}}) instead.
### `selectOptionInTest` has been removed

View File

@ -1,4 +1,6 @@
---
title: Migrate plugins from Grafana version 9.1.x to 9.2.x
menuTitle: v9.1.x to v9.2.x
description: Guide for migrating plugins from Grafana v9.1.x to v9.2.x
keywords:
- grafana
@ -6,8 +8,6 @@ keywords:
- migration
- plugin
- documentation
title: Migrate plugins from Grafana 9.1.x to 9.2.x
menutitle: v9.1.x to v9.2.x
weight: 2100
---

View File

@ -1,4 +1,6 @@
---
title: Migrate plugins from Grafana 9.3.x to 9.4.x
menuTitle: v9.3.x to v9.4.x
description: Guide for migrating plugins from Grafana v9.3.x to v9.4.x
keywords:
- grafana
@ -6,8 +8,6 @@ keywords:
- migration
- plugin
- documentation
title: Migrate plugins from Grafana 9.3.x to 9.4.x
menutitle: v9.3.x to v9.4.x
weight: 2000
---
@ -144,8 +144,8 @@ useEffect(() => {
## Forwarded HTTP headers in the plugin SDK for Go
We recommended to use the `<request>.GetHTTPHeader` or `<request>.GetHTTPHeaders` methods when retrieving forwarded HTTP headers. See [Forward OAuth identity for the logged-in user]({{< relref "add-authentication-for-data-source-plugins.md#forward-oauth-identity-for-the-logged-in-user" >}}), [Forward cookies for the logged-in user
]({{< relref "add-authentication-for-data-source-plugins.md#forward-cookies-for-the-logged-in-user" >}}) or [Forward user header for the logged-in user]({{< relref "add-authentication-for-data-source-plugins.md#forward-user-header-for-the-logged-in-user" >}}) for example usages.
We recommended to use the `<request>.GetHTTPHeader` or `<request>.GetHTTPHeaders` methods when retrieving forwarded HTTP headers. See [Forward OAuth identity for the logged-in user]({{< relref "../../create-a-grafana-plugin/extend-a-plugin/add-authentication-for-data-source-plugins.md#forward-oauth-identity-for-the-logged-in-user" >}}), [Forward cookies for the logged-in user
]({{< relref "../../create-a-grafana-plugin/extend-a-plugin/add-authentication-for-data-source-plugins.md#forward-user-header-for-the-logged-in-user" >}}) or [Forward user header for the logged-in user]({{< relref "../../create-a-grafana-plugin/extend-a-plugin/add-authentication-for-data-source-plugins.md#forward-user-header-for-the-logged-in-user" >}}) for example usages.
### Technical details

View File

@ -1,4 +1,6 @@
---
title: Migrate plugins from Grafana version 9.x to 10.x
menuTitle: v9.x to v10.x
description: Guide for migrating plugins from Grafana v9.x to v10.x
keywords:
- grafana
@ -6,8 +8,6 @@ keywords:
- migration
- plugin
- documentation
title: Migrate plugins from Grafana 9.x to 10.x
menutitle: v9.x to v10.x
weight: 1900
---

View File

@ -329,10 +329,10 @@
},
"routes": {
"type": "array",
"description": "For data source plugins. Proxy routes used for plugin authentication and adding headers to HTTP requests made by the plugin. For more information, refer to [Authentication for data source plugins](https://grafana.com/docs/grafana/latest/developers/plugins/authentication/).",
"description": "For data source plugins. Proxy routes used for plugin authentication and adding headers to HTTP requests made by the plugin. For more information, refer to [Authentication for data source plugins](/docs/grafana/latest/developers/plugins/authentication/).",
"items": {
"type": "object",
"description": "For data source plugins. Proxy routes used for plugin authentication and adding headers to HTTP requests made by the plugin. For more information, refer to [Authentication for data source plugins](https://grafana.com/docs/grafana/latest/developers/plugins/authentication/).",
"description": "For data source plugins. Proxy routes used for plugin authentication and adding headers to HTTP requests made by the plugin. For more information, refer to [Authentication for data source plugins](/docs/grafana/latest/developers/plugins/authentication/).",
"additionalProperties": false,
"properties": {
"path": {

View File

@ -1,11 +1,21 @@
---
description: Topics related to plugin publishing
title: Publish a plugin
title: Publish or sign a plugin
menuTitle: Publish a plugin
keywords:
- grafana
- plugins
- plugin
- publish
- publishing
description: An index to documentation related to plugin publishing and signing.
weight: 400
---
# Publish a plugin
# Publish or sign a plugin
This section contains topics related to publishing Grafana plugins.
This section contains topics related to publishing and signing Grafana plugins.
- [Publishing and signing criteria]({{< relref "../publishing-and-signing-criteria.md">}})
- [Publish or update a plugin]({{< relref "../publish-or-update-a-plugin.md">}})
- [Package a plugin]({{< relref "./package-a-plugin.md" >}})
- [Publishing and signing criteria]({{< relref "./publishing-and-signing-criteria.md" >}})
- [Publish or update a plugin]({{< relref "./publish-or-update-a-plugin.md" >}})
- [Sign a plugin]({{< relref "./sign-a-plugin.md" >}})

View File

@ -1,11 +1,20 @@
---
description: How to package a plugin
title: Package a plugin
keywords:
- grafana
- plugins
- plugin
- links
- package
- packaging
- packages
description: How to package a plugin
weight: 100
---
By packaging a plugin, you can organize the plugin code and make it ready for use in your organization.
# Package a plugin
## Package a plugin for distribution
Package a plugin to organize the plugin code and make it ready for use in your organization. Follow these steps to package the plugin in a ZIP file.
1. Build the plugin
@ -22,7 +31,7 @@ By packaging a plugin, you can organize the plugin code and make it ready for us
Make sure that all the binaries are executable and have a `0755` (`-rwxr-xr-x`) permission.
1. Sign the plugin. To learn more, refer to [Sign the plugin]({{< relref "./sign-a-plugin" >}}).
1. Sign the plugin. To learn more, refer to [Sign a plugin]({{< relref "./sign-a-plugin" >}}).
1. Rename the `dist` directory to match your plugin ID, and then create a ZIP archive.
@ -64,4 +73,4 @@ drwxr-xr-x 0 bx stor 22-Mar-24 23:23 grafana-clickhouse-datasource/img/
22 files, 92516655 bytes uncompressed, 34319591 bytes compressed: 62.9%
```
When you've packaged your plugin, you can proceed to [publishing a plugin]({{< relref "publish-a-plugin.md" >}}) or [installing a packaged plugin](https://grafana.com/docs/grafana/latest/administration/plugin-management/#install-a-packaged-plugin).
When you've packaged your plugin, you can proceed to [publishing a plugin]({{< relref "./publish-or-update-a-plugin.md" >}}) or [installing a packaged plugin](/docs/grafana/latest/administration/plugin-management/#install-a-packaged-plugin).

View File

@ -1,9 +1,17 @@
---
aliases:
- share-a-plugin/
description: Learn how to package and share your plugin.
title: Publish or update a plugin
aliases:
- ../../plugins/publish-a-plugin/
- share-a-plugin/
keywords:
- grafana
- plugins
- plugin
- publish plugin
- update plugin
description: Learn how to package and share your plugin.
type: docs
weight: 300
---
# Publish or update a plugin
@ -19,7 +27,7 @@ By having your plugin published on Grafana.com, more users will be able to disco
When you build a plugin from source, a `dist` folder is created. This folder contains the production build or _plugin assets_ for your plugin.
To package a plugin, refer to [Package a plugin]{{< relref "package-a-plugin.md" >}}).
To package a plugin, refer to [Package a plugin]({{< relref "./package-a-plugin.md" >}}).
### Follow our guidelines
@ -111,11 +119,11 @@ To submit an **update** for an already published plugin:
### Can I distribute my plugin somewhere else other than the Grafana plugin catalog?
- The official method for distributing Grafana plugins is through our catalog. Alternative methods, such as installing private or development plugins on local Grafana instances, are available as per the guidelines provided in [this guide]({{< relref "../../administration/plugin-management#install-plugin-on-local-grafana" >}}).
- The official method for distributing Grafana plugins is through our catalog. Alternative methods, such as installing private or development plugins on local Grafana instances, are available as per the guidelines provided in [this guide]({{< relref "../../../administration/plugin-management#install-plugin-on-local-grafana" >}}).
### Can I still use Angular for my plugin?
- No. We will not accept any new plugin submissions written in Angular. For more information, refer to our [Angular support deprecation documentation]({{< relref "../angular_deprecation" >}}).
- No. We will not accept any new plugin submissions written in Angular. For more information, refer to our [Angular support deprecation documentation]({{< relref "../../angular_deprecation" >}}).
### Do plugin signatures expire?

View File

@ -1,10 +1,22 @@
---
title: Plugin publishing and signing criteria
description: Acceptance criteria for publishing and signing Grafana plugins.
aliases:
- ../../plugins/publishing-and-signing-criteria/
keywords:
- grafana
- plugins
- plugin
- publish plugin
- sign plugin
- publishing
- signing
weight: 200
---
# Plugin publishing and signing criteria
Grafana plugins must adhere to the Grafana Labs [Plugin Policy](https://grafana.com/legal/plugins/). Our review process for publishing and signing will examine your compliance with this policy.
Grafana plugins must adhere to the Grafana Labs [Plugin Policy](/legal/plugins/). Our review process for publishing and signing will examine your compliance with this policy.
> **Important:** Grafana Labs reserves the right to decline or remove any plugin at its discretion. Failure to comply with publishing and signing criteria may result in immediate removal from the Grafana plugin catalog.

View File

@ -1,16 +1,27 @@
---
title: Sign a plugin
aliases:
- ../../sign-a-plugin
- ../../sign-a-plugin/
description: How to sign a Grafana plugin.
keywords:
- grafana
- plugins
- plugin
- sign plugin
- signing plugin
weight: 400
---
# Sign a plugin
Grafana requires all plugins to be signed so that we can verify their authenticity with [signature verification]({{< relref "../../administration/plugin-management#plugin-signatures" >}}).
Grafana requires all plugins to be signed so that we can verify their authenticity with [signature verification]({{< relref "../../../administration/plugin-management#plugin-signatures" >}}).
All Grafana Labs-authored backend plugins, including Enterprise plugins, are signed. By [default]({{< relref "../../administration/plugin-management#allow-unsigned-plugins" >}}), Grafana **requires** all plugins to be signed in order for them to be loaded.
All Grafana Labs-authored backend plugins, including Enterprise plugins, are signed. By [default]({{< relref "../../../administration/plugin-management#allow-unsigned-plugins" >}}), Grafana **requires** all plugins to be signed in order for them to be loaded.
Before you can sign your plugin, you need to decide whether you want to sign it as a _public_ or a _private_ plugin.
To make your plugin publicly available outside of your organization, sign your plugin under a _community_ or _commercial_ [signature level](#plugin-signature-levels). Public plugins are available from the [Grafana plugin catalog](https://grafana.com/plugins) and can be installed by anyone.
To make your plugin publicly available outside of your organization, sign your plugin under a _community_ or _commercial_ [signature level](#plugin-signature-levels). Public plugins are available from the [Grafana plugin catalog](/plugins) and can be installed by anyone.
If you intend to only use the plugin within your organization, sign it under a _private_ [signature level](#plugin-signature-levels).
@ -18,19 +29,19 @@ If you intend to only use the plugin within your organization, sign it under a _
To verify ownership of your plugin, generate an API key that you'll use every time you need to sign a new version of your plugin.
1. [Create a Grafana Cloud account](https://grafana.com/signup).
1. [Create a Grafana Cloud account](/signup).
1. Make sure that the first part of the plugin ID matches the slug of your Grafana Cloud account.
You can find the plugin ID in the `plugin.json` file inside your plugin directory. For example, if your account slug is `acmecorp`, you need to prefix the plugin ID with `acmecorp-`.
1. [Create a Grafana Cloud API key](https://grafana.com/docs/grafana-cloud/reference/create-api-key/) with the **PluginPublisher** role.
1. [Create a Grafana Cloud API key](/docs/grafana-cloud/reference/create-api-key/) with the **PluginPublisher** role.
## Sign a public plugin
Public plugins need to be reviewed by the Grafana team before you can sign them.
1. Submit your plugin for [review]({{< relref "publish-a-plugin/#publishing-your-plugin-for-the-first-time" >}})
1. Submit your plugin for [review]({{< relref "./publish-or-update-a-plugin.md#publish-your-plugin" >}}).
1. If we approve your plugin, you're granted a plugin signature level. You need this signature level to proceed.
1. In your plugin directory, sign the plugin with the API key you just created. Grafana Sign Plugin creates a [MANIFEST.txt](#plugin-manifest) file in the `dist` directory of your plugin:
@ -121,6 +132,6 @@ With a **public** plugin, your plugin doesn't have a plugin signature level assi
### Why do I get a "Field is required: `rootUrls`" error for my private plugin?
With a **private** plugin, you need to add a `rootUrls` flag to the `plugin:sign` command. The `rootUrls` must match the [root_url]({{< relref "../../setup-grafana/configure-grafana/#root_url" >}}) configuration. For more information, refer to [Sign a private plugin](#sign-a-private-plugin).
With a **private** plugin, you need to add a `rootUrls` flag to the `plugin:sign` command. The `rootUrls` must match the [root_url]({{< relref "../../../setup-grafana/configure-grafana#root_url" >}}) configuration. For more information, refer to [Sign a private plugin](#sign-a-private-plugin).
If you still get this error, make sure that the API key was generated by a Grafana Cloud account that matches the first part of the plugin ID.