跳到主要内容

将插件从 Grafana 9.3.x 迁移到 9.4.x

按照以下说明从 Grafana 9.3.x 迁移到 9.4.x。

支持新的导航布局

首先,在 `custom.ini` 中启用 `topnav` 功能标志,检查你的插件在新导航布局中的渲染效果

[feature_toggles]
enable = topnav

从 `onNavChanged` 迁移

如果你的插件使用 `onNavChanged` 回调来通知 Grafana 其导航模型和子页面,你应该会看到这会导致导航元素重复。如果你禁用 `topnav`,则它应该看起来和以前一样。

如果启用了 `topnav`,则我们需要更新插件以利用新的 `PluginPage` 组件。在这种情况下,我们不再调用已弃用的 `onNavChanged`。

切换到 `PluginPage` 组件

Grafana 现在从 `@grafana/runtime` 中暴露了一个新的 `PluginPage` 组件,它与新的导航和页面布局挂钩。当 `topnav` 功能被禁用时,这个新组件也支持旧的页面布局。

新的 `PluginPage` 组件也将处理渲染分区导航。分区导航可以包含其他核心分区和其他插件。为了控制特定插件的分区导航中显示的页面,Grafana 使用添加到 `plugin.json` 中且 `addToNav` 设置为 `true` 的页面。

要使用此组件,只需将其包装在你的页面内容周围即可

import { PluginPage } from '@grafana/runtime';

...

return (
<PluginPage>
{your page content here}
</PluginPage>
);

Grafana 查看 URL 以知道在分区导航中哪个插件和页面应该处于活动状态。因此,此组件仅适用于你在 `plugin.json` 中指定的页面。然后,`PluginPage` 将根据 `plugin.json` 中指定的页面名称渲染页面标题。

对未在 `plugin.json` 中定义的页面使用 `PluginPage`

`PluginPage` 组件还暴露了一个 `pageNav` 属性,该属性是一个 `NavModelItem`。此 `pageNav` 属性对于未在 `plugin.json` 中定义的页面(例如,单个项目页面)非常有用。你在 `pageNav` 模型中指定的 `text` 和 `description` 用于填充面包屑和页面标题。

示例

const pageNav = {
text: 'Write errors cortex-prod-04',
description: 'Incident timeline and details'
};

return (
<PluginPage pageNav={pageNav}>
{your page content here}
</PluginPage>
);

活动页面在面包屑和分区导航中的匹配方式取决于页面路由是分层的。如果你有一个列表页面和一个项目页面,则需要将项目页面设为列表页面的子路由。此外,你还需要在 `plugin.json` 中指定列表页面的 URL。

例如,你可能有一个 `/users` 的用户列表。这意味着特定用户的项目页面需要在 `/users/:id`。这可能需要对你的路由进行一些重构。

配合标签页使用 `PluginPage`

你还可以通过在 `pageNav` 模型中指定 `children` 来创建更深层次的层级,从而创建一个带有标签页导航的页面。

示例

const pageNav = {
text: 'My page',
description: 'Incident timeline and details',
url: '/a/myorgid-pluginname-app',
children: [
{
url: '/a/myorgid-pluginname-app/tab1',
text: 'Tab1',
active: true,
},
{
url: '/a/myorgid-pluginname-app/tab2',
text: 'Tab1',
},
],
};

return (
<PluginPage pageNav={pageNav}>
{your page content here}
</PluginPage>
);

以向后兼容的方式使用 `PluginPage`

如果你想保持与旧版本 Grafana 的向后兼容性,一种方法是实现一个 `PluginPage` 包装器。如果 `PluginPage` 可用并且 `topnav` 功能已启用,则使用真正的 `PluginPage`。在其他情况下,回退到每个插件当前正在做的事情(例如调用 `onNavChanged`)。

示例

import { PluginPageProps, PluginPage as RealPluginPage, config } from '@grafana/runtime';

export const PluginPage = RealPluginPage && config.featureToggles.topnav ? RealPluginPage : PluginPageFallback;

function PluginPageFallback(props: PluginPageProps) {
return props.children;
}

还需要额外的一步(和一个 `if` 块)来根据 `config.features.topnav` 是否为 `true` 来隐藏或显示标签页。你的插件需要在 `useNavModel.ts` 文件中包含这些更改

// useNavModel.ts

import { config } from '@grafana/runtime';

...

export function useNavModel({ meta, rootPath, onNavChanged }: Args) {
const { pathname, search } = useLocation();
useEffect(() => {
if (config.featureToggles.topnav) {
return;
}
}, [config]);

...

Go 插件 SDK 中的转发 HTTP 头

建议在检索转发的 HTTP 头时使用 `.GetHTTPHeader` 或 `.GetHTTPHeaders` 方法。请参阅转发登录用户的 OAuth 身份转发登录用户的 cookies转发登录用户的用户头 以获取使用示例。

技术细节

Grafana Go SDK v0.147.0 引入了一个新的接口 ForwardHTTPHeaders,由 `QueryDataRequest`、`CheckHealthRequest` 和 `CallResourceRequest` 实现。

Grafana v9.4.0 中新引入的转发 HTTP 头是 `X-Grafana-User`、`X-Panel-Id`、`X-Dashboard-Uid`、`X-Datasource-Uid` 和 `X-Grafana-Org-Id`。在内部,我们在这些头前加上 `http_` 前缀,并在 CheckHealthRequest.HeadersQueryDataRequest.Headers 中以 `http_` 的形式发送它们。

我们建议使用 ForwardHTTPHeaders 方法,这样你就可以保证无需使用前缀即可操作 HTTP 头。也就是说,你可以操作 `X-Grafana-User`、`X-Panel-Id`、`X-Dashboard-Uid`、`X-Datasource-Uid` 和 `X-Grafana-Org-Id`。