Docs: Plugin migration guide - chunk 9 (#69420)

* Initial commit

Signed-off-by: Joe Perez <joseph.perez@grafana.com>

* Prettier fixes

Signed-off-by: Joe Perez <joseph.perez@grafana.com>

* Fixes from doc review

---------

Signed-off-by: Joe Perez <joseph.perez@grafana.com>
pull/69592/head
Joseph Perez 2 years ago committed by GitHub
parent a0dd981f85
commit 1a9bc9ca1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      docs/sources/developers/plugins/migration-guide/angular-react/_index.md
  2. 24
      docs/sources/developers/plugins/migration-guide/v6.x-v7.x/_index.md
  3. 40
      docs/sources/developers/plugins/migration-guide/v7.x-v8.x/_index.md
  4. 30
      docs/sources/developers/plugins/migration-guide/v8.3.x-8.4.x/_index.md
  5. 38
      docs/sources/developers/plugins/migration-guide/v8.x-v9.x/_index.md
  6. 20
      docs/sources/developers/plugins/migration-guide/v9.1.x-v9.2.x/_index.md
  7. 54
      docs/sources/developers/plugins/migration-guide/v9.3.x-9.4.x/_index.md
  8. 28
      docs/sources/developers/plugins/migration-guide/v9.x-v10.x/_index.md

@ -6,7 +6,7 @@ keywords:
- migration
- plugin
- documentation
title: Migrating plugins from AngularJS to React
title: Migrate plugins from AngularJS to React
menutitle: Angular to React
weight: 1000
---
@ -18,7 +18,7 @@ If you want to migrate a plugin to Grafana's React-based plugin platform, then w
While there's no standard migration path from an Angular plugin to the new React platform, we’ve learned that one of the easiest ways to migrate is to:
1. Create a new branch called `migrate-to-react`.
1. Start from scratch with one of the templates provided by the [Create-plugin](https://www.npmjs.com/package/@grafana/create-plugin) tool.
1. Start from scratch with one of the templates provided by the [`create-plugin`](https://www.npmjs.com/package/@grafana/create-plugin) tool.
1. Move the existing code into the new plugin incrementally, one component at a time.
## Migrate a panel plugin
@ -49,7 +49,7 @@ export function MyPanel({ options, data, width, height }: Props) {
While all plugins are different, we'd like to share a migration process that has worked for some of our users.
1. Define your configuration model and `ConfigEditor`. For many plugins, the configuration editor is the simplest component so it's a good candidate to start with.
1. Define your configuration model and `ConfigEditor`. For many plugins, the configuration editor is the simplest component, so it's a good candidate to start with.
1. Implement the `testDatasource()` method on the class that extends `DataSourceApi`. Use the settings in your configuration model to make sure that you can successfully configure and access the external API.
1. Implement the `query()` method. At this point, you can hard-code your query, because we haven’t yet implemented the query editor. The `query()` method supports both the new data frame response and the old `TimeSeries` response, so don’t worry about converting to the new format just yet.
1. Implement the `QueryEditor`. How much work this requires depends on how complex your query model is.

@ -6,18 +6,20 @@ keywords:
- migration
- plugin
- documentation
title: Migrating plugins from Grafana version 6.x to 7.x
title: Migrate plugins from Grafana version 6.x to 7.x
menutitle: v6.x to v7.x
weight: 2500
---
# Migrating plugins from Grafana version 6.x to 7.0
# Migrate plugins from Grafana version 6.x to 7.0
Follow the instructions in this section to upgrade Grafana from version 6.x to 7.0.
## What's new in Grafana 7.0?
Grafana 7.0 introduced a whole new plugin platform based on React. The new platform supersedes the previous Angular-based plugin platform.
Grafana 7.0 introduced a whole new plugin platform based on React. This new platform supersedes the previous Angular-based plugin platform.
Plugins built using Angular still work for the foreseeable future, but we encourage new plugin authors to develop with the new platform.
Plugins built using Angular still work in the near term, but we strongly encourage new plugin authors to develop with the new platform.
### New data format
@ -27,7 +29,7 @@ Previously, data source plugins could send data either as time series or tables.
### Improved TypeScript support
While the previous Angular-based plugin SDK did support TypeScript, for the React platform, we’ve greatly improved the support. All our APIs are now TypeScript, which might require existing code to update to the new stricter type definitions. Grafana 7.0 also introduced several new APIs for plugin developers that take advantage of many of the new features in Grafana 7.0.
Although the previous Angular-based plugin SDK supported TypeScript, we’ve greatly improved the support for the React platform. All our APIs are now written in TypeScript, which might require existing code to update to the new stricter type definitions. Grafana 7.0 also introduced several new APIs for plugin developers that take advantage of many of the new features in Grafana 7.0.
### Grafana Toolkit
@ -35,6 +37,8 @@ With Grafana 7.0, we released a new tool for making it easier to develop plugins
For more information, refer to [@grafana/toolkit](https://www.npmjs.com/package/@grafana/toolkit).
{{% admonition type="note" %}} As of Grafana 10.0, `@grafana/toolkit` is deprecated. It is replaced by the [`create-plugin`](https://grafana.github.io/plugin-tools/docs/creating-a-plugin) tool. %}}
### Field options
Grafana 7.0 introduced the concept of _field options_, a new way of configuring your data before it gets visualized. Since this was not available in previous versions, any plugin that enables field-based configuration will not work in previous versions of Grafana.
@ -43,7 +47,7 @@ For plugins prior to Grafana 7.0, all options are considered _Display options_.
### Backend plugins
While backend plugins were available as an experimental feature in previous versions of Grafana, the support has been greatly improved for Grafana 7. Backend plugins for Grafana 7.0 are backwards-compatible and will continue to work. However, the old backend plugin system has been deprecated, and we recommend that you use the new SDK for backend plugins.
While backend plugins were available as an experimental feature in previous versions of Grafana, their support has been greatly improved for Grafana 7. Backend plugins for Grafana 7.0 are backwards-compatible and will continue to work. However, the old backend plugin system has been deprecated, and we recommend that you use the new SDK for backend plugins.
Since Grafana 7.0 introduced signing of backend plugins, community plugins won’t load by default if they’re unsigned.
@ -78,6 +82,8 @@ As of Grafana 7.0, backend plugins can now be cryptographically signed to verify
## From version 6.5.x to 7.3.0
Follow the instructions in this section to upgrade Grafana from version 6.5.x to 7.3.0.
### getColorForTheme changes
The `getColorForTheme` function arguments have changed from `(color: ColorDefinition, theme?: GrafanaThemeType)` to `(color: string, theme: GrafanaTheme)`.
@ -104,6 +110,8 @@ const themeColor = getColorForTheme(color, theme);
## From 6.2.x to v7.4.x
Follow the instructions in this section to upgrade Grafana from version 6.2.x to v7.4.x.
### Legend components
The Legend components have been refactored and introduced the following changes within the `@grafana/ui` package.
@ -116,5 +124,5 @@ import { LegendItem, LegendOptions, GraphLegend } from '@grafana/ui';
import { VizLegendItem, VizLegendOptions, VizLegend } from '@grafana/ui';
```
- `LegendPlacement` has been updated from `'under' | 'right' | 'over'` to `'bottom' | 'right'` so you can not place the legend above the visualization anymore.
- The `isVisible` in the `LegendItem` has been renamed to `disabled` in `VizLegendItem`.
- `LegendPlacement` has been updated from `'under' | 'right' | 'over'` to `'bottom' | 'right'`, so you can't place the legend above the visualization anymore.
- The `isVisible` attribute in the `LegendItem` has been renamed to `disabled` in `VizLegendItem`.

@ -6,26 +6,28 @@ keywords:
- migration
- plugin
- documentation
title: Migrating plugins from Grafana version 7.x to 8.x
title: Migrate plugins from Grafana version 7.x to 8.x
menutitle: v7.x to v8.x
weight: 2400
---
# Migrating plugins from Grafana version 7.x.x to 8.x.x
# Migrate plugins from Grafana version 7.x.x to 8.x.x
This section explains how to migrate Grafana v7.x.x plugins to the updated plugin system available in Grafana v8.x.x. Depending on your plugin, you need to perform one or more of the following steps. We have documented the breaking changes in Grafana v8.x.x and the steps you need to take to upgrade your plugin.
This section explains how to migrate Grafana v7.x.x plugins to the updated plugin system available in Grafana v8.x.x. Depending on your plugin, you need to perform one or more of the following steps.
In this section, we've documented the breaking changes in Grafana v8.x.x and the steps you need to take to upgrade your plugin.
## Backend plugin v1 support has been dropped
Use the new [plugin sdk](https://github.com/grafana/grafana-plugin-sdk-go) to run your backend plugin running in Grafana 8.
Use the new [plugin SDK for Go](https://github.com/grafana/grafana-plugin-sdk-go) to run your backend plugin running in Grafana 8.
### 1. Add dependency on grafana-plugin-sdk-go
Add a dependency on the `https://github.com/grafana/grafana-plugin-sdk-go`. We recommend using [go modules](https://go.dev/blog/using-go-modules) to manage your dependencies.
Add a dependency on the `https://github.com/grafana/grafana-plugin-sdk-go`. We recommend using [Go modules](https://go.dev/blog/using-go-modules) to manage your dependencies.
### 2. Update the way you bootstrap your plugin
Update your `main` package to bootstrap via the new plugin sdk.
Update your `main` package to bootstrap via the new plugin Go SDK.
```go
// before
@ -84,7 +86,7 @@ func main() {
### 3. Update the plugin package
Update your `plugin` package to use the new plugin sdk.
Update your `plugin` package to use the new plugin Go SDK:
```go
// before
@ -150,7 +152,7 @@ func (d *SampleDatasource) CheckHealth(_ context.Context, req *backend.CheckHeal
## Sign and load backend plugins
We strongly recommend that you not allow unsigned plugins in your Grafana installation. By allowing unsigned plugins, we cannot guarantee the authenticity of the plugin, which could compromise the security of your Grafana installation.
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).
@ -184,7 +186,7 @@ The property that defines which Grafana version your plugin supports has been re
## Update imports to match emotion 11
Grafana uses Emotion library to manage frontend styling. We have updated the Emotion package and this can affect your frontend plugin if you have custom styling. You only need to update the import statements to get it working in Grafana 8.
Grafana uses the Emotion library to manage frontend styling. We've updated the Emotion package and this can affect your frontend plugin if you have custom styling. You only need to update the `import` statements to get it working in Grafana 8.
```ts
// before
@ -232,15 +234,17 @@ To make side navigation work properly - app plugins targeting Grafana `8.+` and
## 8.0 deprecations
The following features have been deprecated in version 8.0.
### Grafana theme v1
In Grafana 8 we have introduced a new improved version of our theming system. The previous version of the theming system is still available but is deprecated and will be removed in the next major version of Grafana.
You can find more detailed information on how to apply the v2 theme [here](https://github.com/grafana/grafana/blob/main/contribute/style-guides/themes.md#theming-grafana).
**How to style a functional component**
#### How to style a functional component
The `useStyles` hook is the preferred way to access the theme when styling. It provides basic memoization and access to the theme object.
The `useStyles` hook is the preferred way to access the theme when styling. It provides basic memoization and access to the theme object:
```ts
// before
@ -278,7 +282,9 @@ const getStyles = (theme: GrafanaTheme2) => ({
});
```
**How to use the theme in a functional component**
#### How to use the theme in a functional component
This example shows how to use the theme in a functional component:
```ts
// before
@ -299,7 +305,9 @@ function Component(): ReactElement | null {
}
```
**How to use the theme in a class component**
#### How to use the theme in a class component
This example shows how to use the theme in a class:
```ts
// before
@ -333,9 +341,11 @@ class Component extends React.Component<Props> {
export default withTheme2(Component);
```
**Gradually migrating components**
## Gradual migration of components
If you need to use both the v1 and v2 themes because you've used both migrated and non-migrated components in the same context, then use the `v1` property on the `v2` theme.
If you need to use both the v1 and v2 themes due to using migrated and non-migrated components in the same context, use the `v1` property on the `v2` theme as described in the following example.
**Example:**
```ts
function Component(): ReactElement | null {

@ -6,30 +6,34 @@ keywords:
- migration
- plugin
- documentation
title: Migrating plugins from Grafana version 8.3.x to 8.4.x
title: Migrate plugins from Grafana version 8.3.x to 8.4.x
menutitle: v8.3.x to v8.4.x
weight: 2200
---
# Migrating plugins from Grafana version 8.3.x to 8.4.x
# Migrate plugins from Grafana version 8.3.x to 8.4.x
This section explains how to migrate Grafana v8.3.x plugins to the updated plugin system available in Grafana v8.4.x. Depending on your plugin, you need to perform one or more of the following steps.
## Value Mapping Editor has been removed from @grafana-ui library
Removed due to being an internal component.
Removed because it is an internal component.
## Thresholds Editor has been removed from @grafana-ui library
Removed due to being an internal component.
Removed because it is an internal component.
## 8.4 deprecations
### LocationService replaces getLocationSrv
The following features have been deprecated in version 8.4.
### `LocationService` replaces `getLocationSrv`
In a previous release, we migrated to use a new routing system and introduced a new service for managing locations, navigation, and related information. In this release, we are making that new service the primary service.
**Example:** Import the service.
**Example:**
Import the service:
```ts
// before
@ -39,7 +43,9 @@ import { getLocationSrv } from '@grafana/runtime';
import { locationService } from '@grafana/runtime';
```
**Example:** Navigate to a path and add a new record in the navigation history so that you can navigate back to the previous one.
**Example:**
Navigate to a path and add a new record in the navigation history so that you can navigate back to the previous one:
```ts
// before
@ -52,7 +58,9 @@ getLocationSrv.update({
locationService.push('/route-to-navigate-to');
```
**Example:** Navigate to a path and replace the current record in the navigation history.
**Example:**
Navigate to a path and replace the current record in the navigation history:
```ts
// before
@ -65,7 +73,9 @@ getLocationSrv.update({
locationService.replace('/route-to-navigate-to');
```
**Example:** Update the search or query parameter for the current route and add a new record in the navigation history so that you can navigate back to the previous one.
**Example:**
Update the search or query parameter for the current route and add a new record in the navigation history so that you can navigate back to the previous one:
```ts
// How to navigate to a new path
@ -82,7 +92,7 @@ getLocationSrv.update({
locationService.partial({ value: 1 });
```
**Example:** Update the search or query parameter for the current route and add replacing it in the navigation history.
**Example:** Update the search or query parameter for the current route and add replacing it in the navigation history:
```ts
// before

@ -6,20 +6,24 @@ keywords:
- migration
- plugin
- documentation
title: Migrating plugins from Grafana version 8.x to 9.x
title: Migrate plugins from Grafana version 8.x to 9.x
menutitle: v8.x to v9.x
weight: 2300
---
# Migrating plugins from Grafana version 8.x to 9.x
# Migrate plugins from Grafana version 8.x to 9.x
Follow the instructions in this section to migrate plugins from version 8.x to 9.x.
## 9.0 breaking changes
### theme.visualization.getColorByName replaces getColorForTheme
The following breaking changes are introduced in version 9.0 of Grafana.
### `theme.visualization.getColorByName` replaces `getColorForTheme`
`getColorForTheme` was removed, use `theme.visualization.getColorByName` instead
The `getColorForTheme` was removed, so you should use `theme.visualization.getColorByName` instead.
Example:
**Example:**
```ts
// before
@ -29,11 +33,11 @@ fillColor: getColorForTheme(panel.sparkline.fillColor, config.theme)
fillColor: config.theme.visualization.getColorByName(panel.sparkline.fillColor),
```
### VizTextDisplayOptions replaces TextDisplayOptions
### `VizTextDisplayOptions` replaces `TextDisplayOptions`
`TextDisplayOptions` was removed, use `VizTextDisplayOptions` instead
The `TextDisplayOptions` was removed, so you should use `VizTextDisplayOptions` instead.
Example:
**Example:**
```ts
// before
@ -53,7 +57,7 @@ text?: VizTextDisplayOptions;
### Changes in the internal of `backendSrv.fetch()`
We have changed the internals of `backendSrv.fetch()` to throw an error when the response is an incorrect JSON. Make sure to handle possible errors on the callsite where using `backendSrv.fetch()` (or any other `backendSrv` methods)
We have changed the internals of `backendSrv.fetch()` to throw an error when the response is an incorrect JSON. Make sure to handle possible errors on the callsite where using `backendSrv.fetch()` (or any other `backendSrv` methods).
```ts
// PREVIOUSLY: this was returning with an empty object {} - in case the response is an invalid JSON
@ -63,17 +67,17 @@ return await getBackendSrv().post(`${API_ROOT}/${id}/install`);
return await getBackendSrv().post(`${API_ROOT}/${id}/install`);
```
### GrafanaTheme2 and useStyles2 replaces getFormStyles
### `GrafanaTheme2` and `useStyles2` replaces `getFormStyles`
We have removed the deprecated `getFormStyles` function from [grafana-ui](https://www.npmjs.com/package/@grafana/ui). Use `GrafanaTheme2` and the `useStyles2` hook instead
We have removed the deprecated `getFormStyles` function from [grafana-ui](https://www.npmjs.com/package/@grafana/ui). Use `GrafanaTheme2` and the `useStyles2` hook instead.
### /api/ds/query replaces /api/tsdb/query
### `/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
### `selectOptionInTest` has been removed
The `@grafana/ui` package helper function `selectOptionInTest` used in frontend tests has been removed as it caused testing libraries to be bundled in the production code of Grafana. If you were using this helper function in your tests please update your code accordingly:
The `@grafana/ui` package helper function `selectOptionInTest` used in frontend tests has been removed because it caused testing libraries to be bundled in the production code of Grafana. If you were using this helper function in your tests, then update your code accordingly:
```ts
// before
@ -89,9 +93,9 @@ await select(selectEl, 'Option 2', { container: document.body });
### Toolkit 9 and webpack
Plugins using custom Webpack configs could potentially break due to the changes between webpack@4 and webpack@5. Please refer to the [official migration guide](https://webpack.js.org/migrate/5/) for assistance.
Plugins using custom Webpack configs could potentially break due to the changes between webpack@4 and webpack@5. Please refer to the [official webpack migration guide](https://webpack.js.org/migrate/5/) for assistance.
Webpack 5 does not include polyfills for node.js core modules by default (e.g. `buffer`, `stream`, `os`). This can result in failed builds for plugins. If polyfills are required it is recommended to create a custom webpack config in the root of the plugin repo and add the required fallbacks:
Webpack 5 does not include polyfills for node.js core modules by default (for example, `buffer`, `stream`, `os`). This can result in failed builds for plugins. If polyfills are required, then it is recommended to create a custom webpack config in the root of the plugin repo and add the required fallbacks:
```js
// webpack.config.js

@ -6,18 +6,20 @@ keywords:
- migration
- plugin
- documentation
title: Migrating plugins from Grafana 9.1.x to 9.2.x
title: Migrate plugins from Grafana 9.1.x to 9.2.x
menutitle: v9.1.x to v9.2.x
weight: 2100
---
# Migrating plugins from Grafana version 9.1.x to 9.2.x
# Migrate plugins from Grafana version 9.1.x to 9.2.x
Follow the instructions in this section to migrate plugins from Grafana version 9.1.x to 9.2.x.
## React and React-dom as peer dependencies
In earlier versions of Grafana packages `react` and `react-dom` were installed during a `yarn install` regardless of a plugins dependencies. In 9.2.0 the `@grafana` packages declare these react packages as peerDependencies and will need adding to a plugins `package.json` file for test commands to continue to run successfully.
In earlier versions of Grafana packages, `react` and `react-dom` were installed during a `yarn install` command regardless of a plugin's dependencies. In version 9.2.0, the `@grafana` packages declare these React packages as `peerDependencies` and must be added to a plugin's `package.json` file for test commands.
Example:
**Example:**
```json
// before
@ -36,11 +38,11 @@ Example:
```
## NavModelItem requires a valid icon name
## `NavModelItem` requires a valid icon name
The typings of the `NavModelItem` have improved to only allow a valid `IconName` for the icon property. You can find the complete list of valid icons [here](https://github.com/grafana/grafana/blob/v9.2.0-beta1/packages/grafana-data/src/types/icon.ts). The icons specified in the list will work for older versions of Grafana 9.
The typings of the `NavModelItem` have improved to only allow a valid `IconName` for the icon property. For a complete list of valid icons, refer to the [source code](https://github.com/grafana/grafana/blob/v9.2.0-beta1/packages/grafana-data/src/types/icon.ts). These icons will work for older versions of Grafana 9.
Example:
**Example:**
```ts
// before
@ -62,9 +64,9 @@ const model: NavModelItem = {
## Additional type availability
FieldProps, ModalProps, and QueryFieldProps are now exposed from `@grafana/ui`. They can be imported in the same way as other types.
`FieldProps`, `ModalProps`, and `QueryFieldProps` are now exposed from `@grafana/ui`. They can be imported in the same way as other types.
Example:
**Example:**
```ts
import { FieldProps, ModalProps, QueryFieldProps } from '@grafana/ui';

@ -6,14 +6,16 @@ keywords:
- migration
- plugin
- documentation
title: Migrating plugins from Grafana 9.3.x to 9.4.x
title: Migrate plugins from Grafana 9.3.x to 9.4.x
menutitle: v9.3.x to v9.4.x
weight: 2000
---
# Migrating plugins from Grafana 9.3.x to 9.4.x
# Migrate plugins from Grafana 9.3.x to 9.4.x
## Supporting new navigation layout
Follow the instructions in this section to migrate from Grafana 9.3.x to 9.4.x.
## New navigation layout is supported
First, enable the `topnav` feature flag in `custom.ini` to check how your plugin renders in the new navigation layout:
@ -24,15 +26,17 @@ enable = topnav
### Migrate from `onNavChanged`
If your plugin uses the `onNavChanged` callback to inform Grafana of its nav model & sub pages, you should see that this results in duplicated navigation elements. If you disable `topnav` it should look just as before.
If your plugin uses the `onNavChanged` callback to inform Grafana of its navigation model and child pages, you should see that this results in duplicated navigation elements. If you disable `topnav`, then it should look just like before.
When `topnav` is enabled we need to update the plugin to take advantage of the new `PluginPage` component and not call `onNavChanged`. `onNavChanged` is now deprecated.
If `topnav` is enabled, then we need to update the plugin to take advantage of the new `PluginPage` component. In this case, we do not call `onNavChanged`, which is now deprecated.
### Switch to `PluginPage` component
Grafana now exposes a new `PluginPage` component from `@grafana/runtime` that hooks into the new navigation and page layouts and supports the old page layouts when the `topnav` feature is disabled. This new component will also handle rendering the section navigation. The section navigation can include other core sections and other plugins. To control what pages are displayed in the section navigation for a specific plugin, Grafana will use the pages added in `plugin.json` that have `addToNav` set to `true`.
Grafana now exposes a new `PluginPage` component from `@grafana/runtime` that hooks into the new navigation and page layouts. This new component also supports the old page layouts when the `topnav` feature is disabled.
The new `PluginPage` component will also handle rendering the section navigation. The section navigation can include other core sections and other plugins. To control what pages are displayed in the section navigation for a specific plugin, Grafana uses the pages that have been added in `plugin.json` in which `addToNav` was set to `true`.
This component is very easy to use. Simply wrap it around your page content:
To use this component, simply wrap it around your page content:
```tsx
import { PluginPage } from '@grafana/runtime';
@ -46,13 +50,13 @@ return (
);
```
Grafana will look at the URL to know what plugin and page should be active in the section nav, so this only works for pages you have specified in `plugin.json`. `PluginPage` will then render a page header based on the page name specified in `plugin.json`.
Grafana looks at the URL to know what plugin and page should be active in the section nav. Accordingly, this component only works for pages that you have specified in `plugin.json`. The `PluginPage` will then render a page header based on the page name specified in `plugin.json`.
### Using `PluginPage` for pages not defined in `plugin.json`
### Use `PluginPage` for pages not defined in `plugin.json`
The `PluginPage` component also exposes a `pageNav` property that is a `NavModelItem`. This `pageNav` property is useful for pages that are not defined in `plugin.json` (e.g. individual item pages). The `text` and `description` you specify in the `pageNav` model will be used to populate the breadcrumbs and page header.
The `PluginPage` component also exposes a `pageNav` property that is a `NavModelItem`. This `pageNav` property is useful for pages that are not defined in `plugin.json` (for example, individual item pages). The `text` and `description` that you specify in the `pageNav` model are used to populate the breadcrumbs and the page header.
Example:
**Example:**
```tsx
const pageNav = {
@ -67,13 +71,15 @@ return (
);
```
The way the active page is matched in the breadcrumbs and section nav relies on the page routes being hierarchical. If you have a list page and an item page, the item page needs to be a subroute of the list page and the list page url needs to be specified in your `plugin.json`. For example, you might have a list of users at `/users`. This means that the item page for a specific user needs to be at `/users/:id`. This may require some refactoring of your routes.
The way the active page is matched in the breadcrumbs and section nav relies on the page routes being hierarchical. If you have a list page and an item page, then you need to make the item page into a subroute of the list page. Furthermore, you also need to specify the list page URL in your `plugin.json`.
### Using `PluginPage` with tabs
For example, you might have a list of users at `/users`. This means that the item page for a specific user needs to be at `/users/:id`. This may require some refactoring of your routes.
You can also create a further layer of hierarchy by specifying `children` in the `pageNav` model to created a page with tabbed navigation.
### Use `PluginPage` with tabs
Example:
You can also create a further layer of hierarchy by specifying `children` in the `pageNav` model to create a page with tabbed navigation.
**Example:**
```tsx
const pageNav = {
@ -100,11 +106,11 @@ return (
);
```
### Using `PluginPage` in a backwards-compatible way
### Use `PluginPage` in a backwards-compatible way
If you want to maintain backwards-compatibility with older versions of Grafana, one way is to implement a `PluginPage` wrapper. If `PluginPage` is available and the `topnav` feature is enabled then use the real `PluginPage`, otherwise fallback to whatever each plugin is doing today (including calling `onNavChanged`).
If you want to maintain backwards-compatibility with older versions of Grafana, one way is to implement a `PluginPage` wrapper. If `PluginPage` is available and the `topnav` feature is enabled, then use the real `PluginPage`. In other scenarios, fall back to whatever each plugin is doing today (such as making a call to `onNavChanged`).
Example:
**Example:**
```tsx
import { PluginPageProps, PluginPage as RealPluginPage, config } from '@grafana/runtime';
@ -116,7 +122,7 @@ function PluginPageFallback(props: PluginPageProps) {
}
```
There’s an additional step (and if block) needed to hide/show tabs depending on if `config.features.topnav` is `true`. These changes will need to be made in the `useNavModel.ts` file in your plugin:
There’s an additional step (and `if` block) that is needed to hide or show tabs depending on whether `config.features.topnav` is `true`. Your plugin needs to include these changes in the `useNavModel.ts` file:
```tsx
// useNavModel.ts
@ -136,13 +142,15 @@ useEffect(() => {
...
```
## Forwarded HTTP headers in grafana-plugin-sdk-go
## Forwarded HTTP headers in the plugin SDK for Go
It's 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
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.
### Technical details
The grafana-plugin-sdk-go [v0.147.0](https://github.com/grafana/grafana-plugin-sdk-go/releases/tag/v0.147.0) introduces a new interface [ForwardHTTPHeaders](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go@v0.147.0/backend#ForwardHTTPHeaders) that `QueryDataRequest`, `CheckHealthRequest` and `CallResourceRequest` implements.
The Grafana SDK for Go [v0.147.0](https://github.com/grafana/grafana-plugin-sdk-go/releases/tag/v0.147.0) introduces a new interface [ForwardHTTPHeaders](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go@v0.147.0/backend#ForwardHTTPHeaders) that `QueryDataRequest`, `CheckHealthRequest` and `CallResourceRequest` implements.
Newly introduced forwarded HTTP headers in Grafana v9.4.0 are `X-Grafana-User`, `X-Panel-Id`, `X-Dashboard-Uid`, `X-Datasource-Uid` and `X-Grafana-Org-Id`. Internally, we prefix these with `http_` and they are sent as `http_<HTTP header name>` in [CheckHealthRequest.Headers](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go@v0.147.0/backend#CheckHealthRequest) and [QueryDataRequest.Headers](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go@v0.147.0/backend#QueryDataRequest).
Newly introduced forwarded HTTP headers in Grafana v9.4.0 are `X-Grafana-User`, `X-Panel-Id`, `X-Dashboard-Uid`, `X-Datasource-Uid` and `X-Grafana-Org-Id`. Internally these are prefixed with `http_` and sent as `http_<HTTP header name>` in [CheckHealthRequest.Headers](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go@v0.147.0/backend#CheckHealthRequest) and [QueryDataRequest.Headers](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go@v0.147.0/backend#QueryDataRequest). By using the [ForwardHTTPHeaders](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go@v0.147.0/backend#ForwardHTTPHeaders) methods you're guaranteed to be able to operate on HTTP headers without using the prefix, i.e. `X-Grafana-User`, `X-Panel-Id`, `X-Dashboard-Uid`, `X-Datasource-Uid` and `X-Grafana-Org-Id`.
We recommend using the [ForwardHTTPHeaders](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go@v0.147.0/backend#ForwardHTTPHeaders) methods so that you're guaranteed to be able to operate on HTTP headers without using the prefix. That is, you can operate on `X-Grafana-User`, `X-Panel-Id`, `X-Dashboard-Uid`, `X-Datasource-Uid` and `X-Grafana-Org-Id`.

@ -6,29 +6,31 @@ keywords:
- migration
- plugin
- documentation
title: Migrating plugins from Grafana 9.x to 10.x
title: Migrate plugins from Grafana 9.x to 10.x
menutitle: v9.x to v10.x
weight: 1900
---
# Migrating plugins from Grafana version 9.x to 10.x
# Migrate plugins from Grafana version 9.x to 10.x
## Verifying plugin behaviour with React 18
## Verify plugin behavior with React 18
Grafana 10 includes our upgrade to React 18 and use of the new React client rendering API. These changes were delivered to the core `grafana` repo with [PR 64428](https://github.com/grafana/grafana/pull/64428).
Grafana 10 includes our upgrade to React 18 and use of the new React client-side rendering API. These changes were delivered to the core `grafana` repo with [PR 64428](https://github.com/grafana/grafana/pull/64428).
Whilst this brings us many significant benefits, there's a potential for this to impact the way your plugin works. In particular, there could be unintended side effects caused by the changes around improving consistency with `useEffect` timings and automatic batching of state updates.
Although these updates bring many significant benefits, there's a potential for them to impact the way that your plugin works. In particular, there could be unintended side effects caused by the changes around improving consistency with `useEffect` timings and automatic batching of state updates.
Recommended actions:
**Recommended actions:**
- Review the React 18 [upgrade docs](https://react.dev/blog/2022/03/08/react-18-upgrade-guide)
- Test your plugins against one of the latest [grafana-dev docker images](https://hub.docker.com/r/grafana/grafana-dev/tags?page=1) (for example, [this one](https://hub.docker.com/layers/grafana/grafana-dev/10.0.0-111404pre/images/sha256-ac78acf54b44bd2ce7e68b796b1df47030da7f35e53b02bc3eec3f4de05f780f?context=explore))
- Add a comment to the [forum discussion](https://community.grafana.com/t/grafana-10-is-upgrading-to-react-18/86051) if your plugin is impacted in any way. Either to socialise the changes needed for your plugin or to reach out and ask for help yourself.
- Review the React 18 [upgrade docs](https://react.dev/blog/2022/03/08/react-18-upgrade-guide).
- Test your plugins against one of the latest [grafana-dev docker images](https://hub.docker.com/r/grafana/grafana-dev/tags?page=1) (for example, [this one](https://hub.docker.com/layers/grafana/grafana-dev/10.0.0-111404pre/images/sha256-ac78acf54b44bd2ce7e68b796b1df47030da7f35e53b02bc3eec3f4de05f780f?context=explore)).
- If your plugin is affected, add a comment to the [forum discussion](https://community.grafana.com/t/grafana-10-is-upgrading-to-react-18/86051). Be sure to communicate with us so we are aware of the issue and can provide help.
## DataFrame field values are now just arrays
## Data frame field values are now just arrays
In Grafana 10, the values in DataFrames are now managed as simple JavaScript arrays (see [#66480](https://github.com/grafana/grafana/issues/66480)). It is no longer necessary to wrap values in a [Vector<T>](https://github.com/grafana/grafana/blob/v9.5.x/packages/grafana-data/src/types/vector.ts) implementation. Most code targeting 9.x will continue to work without any issues. In the rare case that existing code directly implements [Vector<T>](https://github.com/grafana/grafana/blob/v9.5.x/packages/grafana-data/src/types/vector.ts) rather than extending/using base classes, this should either return an array or extend [FunctionalVector<T>](https://github.com/grafana/grafana/blob/v10.0.x/packages/grafana-data/src/vector/FunctionalVector.ts#L9). All Vector implementations have been deprecated and will be removed in the future.
In Grafana 10, the values in data frames are now managed as simple JavaScript arrays (see [PR #66480](https://github.com/grafana/grafana/issues/66480)). It is no longer necessary to wrap values in a [Vector<T>](https://github.com/grafana/grafana/blob/v9.5.x/packages/grafana-data/src/types/vector.ts) implementation.
When writing plugins that should run on 9.x, continue to use the Vector interfaces; when targeting 10+ you can now use simple arrays rather than wrapper classes.
Most code targeting 9.x will continue to work without any issues. An exception is the rare case in which existing code directly implements [Vector<T>](https://github.com/grafana/grafana/blob/v9.5.x/packages/grafana-data/src/types/vector.ts) rather than extending or using base classes. In this case, the code should either return an array or extend [FunctionalVector<T>](https://github.com/grafana/grafana/blob/v10.0.x/packages/grafana-data/src/vector/FunctionalVector.ts#L9). All Vector implementations have been deprecated and will be removed in the future.
To make this transition seamless, the Original JavaScript Sin™ was employed: the native Array prototype [had to be extended](https://github.com/grafana/grafana/blob/v10.0.x/packages/grafana-data/src/types/vector.ts) with several Vector methods. We will atone and undo this in v11, when Vector interfaces and classes are removed.
When writing plugins that should run on 9.x, continue to use the Vector interfaces. In this case, when targeting versions 10+, you can now use simple arrays rather than wrapper classes.
To make this transition seamless, we employed the Original JavaScript Sin™. That is, we[extended the native Array prototype](https://github.com/grafana/grafana/blob/v10.0.x/packages/grafana-data/src/types/vector.ts) with several Vector methods. We will atone and undo this in v11, when Vector interfaces and classes are removed.

Loading…
Cancel
Save