mcpField
G
grafana-scenes

grafana-scenes

github.com/grafana开发2954.2k 次安装1 天前更新
代码仓库

关于 grafana-scenes

@grafana/scenes 是供开发者构建 Grafana 插件数据页面的框架。它以声明式场景对象树组织查询、变量、时间范围、布局、面板和导航。

主要功能

  1. 01用场景对象组合页面
  2. 02管理查询、变量和时间范围
  3. 03使用 PanelBuilders 构建面板
  4. 04添加下钻导航和标签页
  5. 05转换查询数据

适用场景

  1. 01创建数据驱动的插件页面
  2. 02构建 Grafana 下钻视图
  3. 03将详情视图组织为标签页

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/grafana/skills --skill grafana-scenes

安装后在 Claude Code 中输入/grafana-scenes确认已加载。

详细介绍

@grafana/scenes 框架

使用声明式场景对象,构建响应式、数据驱动的 Grafana 插件页面。

核心概念

Scenes 由一棵对象树组成:SceneApp → SceneAppPage → EmbeddedScene → 布局 → 面板。每个节点都可以拥有数据($data)、变量($variables)、时间范围($timeRange)和行为($behaviors),并将它们沿树向下传递。

快速入门:新建场景页面

1. 创建场景文件
// src/components/scenes/MyFeature/scene.tsx
import {
  EmbeddedScene, SceneFlexLayout, SceneFlexItem,
  SceneQueryRunner, SceneVariableSet, QueryVariable,
  PanelBuilders, VariableValueSelectors, SceneControlsSpacer,
} from '@grafana/scenes';

export function getMyFeatureScene(params: { datasource: DataSourceRef }) {
  const queryRunner = new SceneQueryRunner({
    datasource: params.datasource,
    queries: [{ refId: 'A', expr: 'up{cluster=~"$cluster"}', instant: true, format: 'table' }],
  });

  const panel = PanelBuilders.table()
    .setData(queryRunner)
    .setTitle('My Table')
    .build();

  return new EmbeddedScene({
    $variables: new SceneVariableSet({
      variables: [
        new QueryVariable({
          name: 'cluster',
          query: 'label_values(up, cluster)',
          datasource: params.datasource,
          isMulti: true, includeAll: true, defaultToAll: true,
        }),
      ],
    }),
    controls: [new VariableValueSelectors({}), new SceneControlsSpacer()],
    body: new SceneFlexLayout({
      direction: 'column',
      children: [new SceneFlexItem({ body: panel })],
    }),
  });
}
2. 创建页面
// src/components/scenes/MyFeature/MyFeature.tsx
import { SceneAppPage, SceneTimeRange } from '@grafana/scenes';

export function getMyFeaturePage(params) {
  return new SceneAppPage({
    title: 'My Feature',
    url: '/a/my-plugin-id/my-feature',
    routePath: 'my-feature/*',
    $timeRange: new SceneTimeRange({ from: 'now-1h', to: 'now' }),
    getScene: () => getMyFeatureScene(params),
    drilldowns: [],
  });
}
3. 在 SceneApp 中注册

将页面添加到根场景文件中的 SceneApp 页面数组。

关键模式

钻取(点击跳转导航)
drilldowns: [{
  routePath: ':cluster/*',
  getPage: (match, parent) => new SceneAppPage({
    title: decodeURIComponent(match.params.cluster),
    url: `${parent.state.url}/${match.params.cluster}`,
    routePath: `${match.params.cluster}/*`,
    getScene: () => detailScene(decodeURIComponent(match.params.cluster)),
  }),
}]
标签页(详情视图中的子页面)

在 SceneAppPage 上传入 tabs: [SceneAppPage, ...],而不是使用 getScene。每个标签页本身都是一个拥有独立场景的 SceneAppPage。

使用转换的查询

将 SceneQueryRunner 包装在 SceneDataTransformer 中,以应用 Grafana 转换或自定义 RxJS 运算符:

new SceneDataTransformer({
  $data: queryRunner,
  transformations: [
    { id: 'organize', options: { renameByName: { 'Value #A': 'CPU' } } },
    (ctx) => (source) => source.pipe(map((frames) => /* custom transform */)),
  ],
})
自定义场景对象

扩展 SceneObjectBase,并通过静态 Component 构建自定义交互式 UI:

class MyWidget extends SceneObjectBase<MyWidgetState> {
  static Component = ({ model }: SceneComponentProps<MyWidget>) => {
    const state = model.useState();
    return <div>{state.value}</div>;
  };
}
表格列覆盖

构建 ConfigOverrideRule 对象,用于钻取链接、筛选、单位、宽度和自定义单元格。

面板类型

PanelBuilders.table()、.timeseries()、.stat()、.gauge()、.barchart() — 链式调用 .setData()、.setTitle()、.setUnit()、.setOption()、.setOverrides(),然后调用 .build()。

常见问题

  • 对于带有钻取或标签页的页面,始终使用 routePath: 'path/*'(包含通配符)
  • URL 参数使用 encodeURIComponent/decodeURIComponent — K8s 名称可能包含 /
  • 查询中引用为 $varName 的变量必须存在于某个祖先 SceneVariableSet 中
  • getScene 会延迟调用;不要在工厂函数中创建副作用
  • 对于即时查询,同时设置 instant: true 和 format: 'table'

资源

评论

支持 Markdown