mcpField
G
grafana-scenes

grafana-scenes

github.com/grafana開発2954.2k 回インストール1 日前に更新
リポジトリ

grafana-scenes について

@grafana/scenesは、Grafanaプラグインでデータ駆動型ページを構築する開発者向けフレームワークです。宣言的なシーンオブジェクトのツリーで、クエリ、変数、時間範囲、レイアウト、パネル、ナビゲーションを構成します。

主な機能

  1. 01シーンオブジェクトによるページ構成
  2. 02クエリ、変数、時間範囲の管理
  3. 03PanelBuildersによるパネル構築
  4. 04ドリルダウンとタブの追加
  5. 05クエリデータの変換

活用シーン

  1. 01データ駆動型プラグインページの作成
  2. 02Grafanaのドリルダウンビューの構築
  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 の pages 配列にページを追加します。

主なパターン

ドリルダウン(クリックして移動するナビゲーション)
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 で getScene の代わりに tabs: [SceneAppPage, ...] を渡します。各タブは、それぞれ独自のシーンを持つ 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 を拡張し、カスタムのインタラクティブ UI 用に静的な Component を定義します。

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' の両方を設定します

リソース

コメント