跳转到主要内容

从 Grafana 版本 7.x 迁移插件到 8.x

遵循以下说明将 Grafana v7.x.x 插件迁移到 Grafana v8.x.x 中可用的更新插件系统。根据您的插件,您可能需要执行以下步骤之一或多个。

请注意 Grafana v8.x.x 中的破坏性变更(如下文所述),以及您需要采取的升级插件步骤。

后端插件 v1 支持已被删除

使用新的 Go 插件 SDK 在 Grafana 8 中运行您的后端插件。

1. 添加对 grafana-plugin-sdk-go 的依赖

添加对 https://github.com/grafana/grafana-plugin-sdk-go 的依赖。我们建议使用 Go 模块 来管理您的依赖项。

2. 更新启动插件的方式

将您的 main 包更新为通过新的插件 Go SDK 启动。

// before
package main

import (
"github.com/grafana/grafana_plugin_model/go/datasource"
hclog "github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"

"github.com/myorgid/datasource/pkg/plugin"
)

func main() {
pluginLogger.Debug("Running GRPC server")

ds, err := NewSampleDatasource(pluginLogger);
if err != nil {
pluginLogger.Error("Unable to create plugin");
}

plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "grafana_plugin_type",
MagicCookieValue: "datasource",
},
Plugins: map[string]plugin.Plugin{
"myorgid-datasource": &datasource.DatasourcePluginImpl{Plugin: ds},
},
GRPCServer: plugin.DefaultGRPCServer,
})
}

// after
package main

import (
"os"

"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"

"github.com/myorgid/datasource/pkg/plugin"
)

func main() {
log.DefaultLogger.Debug("Running GRPC server")

if err := datasource.Manage("myorgid-datasource", NewSampleDatasource, datasource.ManageOpts{}); err != nil {
log.DefaultLogger.Error(err.Error())
os.Exit(1)
}
}

3. 更新插件包

将您的 plugin 包更新为使用新的插件 Go SDK

// before
package plugin

import (
"context"

"github.com/grafana/grafana_plugin_model/go/datasource"
"github.com/hashicorp/go-hclog"
)

func NewSampleDatasource(pluginLogger hclog.Logger) (*SampleDatasource, error) {
return &SampleDatasource{
logger: pluginLogger,
}, nil
}

type SampleDatasource struct{
logger hclog.Logger
}

func (d *SampleDatasource) Query(ctx context.Context, tsdbReq *datasource.DatasourceRequest) (*datasource.DatasourceResponse, error) {
d.logger.Info("QueryData called", "request", req)
// logic for querying your datasource.
}

// after
package plugin

import (
"context"

"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/data"
)

func NewSampleDatasource(_ backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return &SampleDatasource{}, nil
}

type SampleDatasource struct{}


func (d *SampleDatasource) Dispose() {
// Clean up datasource instance resources.
}

func (d *SampleDatasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
log.DefaultLogger.Info("QueryData called", "request", req)
// logic for querying your datasource.
}

func (d *SampleDatasource) CheckHealth(_ context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
log.DefaultLogger.Info("CheckHealth called", "request", req)
// The main use case for these health checks is the test button on the
// datasource configuration page which allows users to verify that
// a datasource is working as expected.
}

签名并加载后端插件

我们强烈建议您不要在 Grafana 安装中允许未签名插件。允许未签名插件,我们无法保证插件的真伪,这可能会危及您的 Grafana 安装的安全性。

要签名您的插件,请参阅签名插件

您仍然可以通过在 开发模式 下运行您的 Grafana 实例来运行和开发未签名的插件。或者,您可以使用 allow_loading_unsigned_plugins 配置设置。

将 react-hook-form 从 v6 更新到 v7

我们已经将 react-hook-form 从版本 6 升级到版本 7。要使您的表单与版本 7 兼容,请参阅 react-hook-form 迁移指南

更新 plugin.json

定义您的插件支持哪些 Grafana 版本的属性已被重命名,现在它是一个范围而不是特定版本。

// before
{
"dependencies": {
"grafanaVersion": "7.5.x",
"plugins": []
}
}

// after
{
"dependencies": {
"grafanaDependency": ">=8.0.0",
"plugins": []
}
}

更新导入以匹配 emotion 11

Grafana 使用 Emotion 库来管理前端样式。我们已经更新了 Emotion 包,这可能会影响您具有自定义样式的插件。您只需更新 import 语句即可使其在 Grafana 8 中正常工作。

// before
import { cx, css } from 'emotion';

// after
import { cx, css } from '@emotion/css';

需要更新的应用程序插件使用仪表板

要使侧导航正常工作 - 针对 Grafana 8.+ 的应用程序插件并通过 addToNav 属性集成到侧菜单,需要调整其 plugin.json 和所有仪表板 json 文件以具有匹配的 uid

plugin.json

{
"id": "plugin-id",
// ...
"includes": [
{
"type": "dashboard",
"name": "(Team) Situation Overview",
"path": "dashboards/example-dashboard.json",
"addToNav": true,
"defaultNav": false,
"uid": "l3KqBxCMz"
}
]
// ...
}

dashboards/example-dashboard.json

{
// ...
"title": "Example Dashboard",
"uid": "l3KqBxCMz",
"version": 1
// ...
}

8.0 弃用

以下功能已在 8.0 版本中弃用。

Grafana 主题 v1

在 Grafana 8 中,我们引入了主题系统的新改进版本。旧版本的主题系统仍然可用,但已弃用,将在 Grafana 的下一个主要版本中删除。

有关如何应用 v2 主题的更详细信息,请参阅此处

如何样式化功能组件

useStyles 钩子是访问主题样式时的首选方法。它提供了基本的记忆化以及访问主题对象的功能。

// before
import React, { ReactElement } from 'react';
import css from 'emotion';
import { GrafanaTheme } from '@grafana/data';
import { useStyles } from '@grafana/ui';

function Component(): ReactElement | null {
const styles = useStyles(getStyles);
}

const getStyles = (theme: GrafanaTheme) => ({
myStyle: css`
background: ${theme.colors.bodyBg};
display: flex;
`,
});

// after
import React, { ReactElement } from 'react';
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';

function Component(): ReactElement | null {
const theme = useStyles2(getStyles);
}

const getStyles = (theme: GrafanaTheme2) => ({
myStyle: css`
background: ${theme.colors.background.canvas};
display: flex;
`,
});

如何在功能组件中使用主题

此示例展示了如何在功能组件中使用主题。

// before
import React, { ReactElement } from 'react';
import { useTheme } from '@grafana/ui';

function Component(): ReactElement | null {
const theme = useTheme();
}

// after
import React, { ReactElement } from 'react';
import { useTheme2 } from '@grafana/ui';

function Component(): ReactElement | null {
const theme = useTheme2();
// Your component has access to the theme variables now
}

如何在类组件中使用主题

此示例展示了如何在类组件中使用主题。

// before
import React from 'react';
import { Themeable, withTheme } from '@grafana/ui';

type Props = {} & Themeable;

class Component extends React.Component<Props> {
render() {
const { theme } = this.props;
// Your component has access to the theme variables now
}
}

export default withTheme(Component);

// after
import React from 'react';
import { Themeable2, withTheme2 } from '@grafana/ui';

type Props = {} & Themeable2;

class Component extends React.Component<Props> {
render() {
const { theme } = this.props;
// Your component has access to the theme variables now
}
}

export default withTheme2(Component);

组件的逐步迁移

如果你需要同时使用 v1 和 v2 主题,因为你已经在同一个上下文中使用了迁移和非迁移的组件,那么在 v2 主题上使用 v1 属性。

示例

function Component(): ReactElement | null {
const theme = useTheme2();
return (
<NonMigrated theme={theme.v1}>
<Migrated theme={theme] />
</NonMigrate>
);
};