跳至主要内容

将插件从 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 主题的更多详细信息 here

如何为函数组件设置样式

useStyles hook 是在设置样式时访问主题的首选方法。它提供基本的记忆功能和对主题对象的访问

// 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>
);
};