Grafana Scenes

repository·main·Indexed 41 days ago

https://github.com/grafana/scenes

A framework and SDK for building highly interactive, dynamic dashboards and applications within the Grafana ecosystem. Version 0.15.0 provides built-in support for template variables, versatile layouts, panel rendering, and URL synchronization. The project includes the core @grafana/scenes SDK and @grafana/scenes-react for React-based development.

Tokens
44.5K
Snippets
111
Records
173
Agent score
53%

What's inside Grafana Scenes

  1. Overview of Scenes App Template

    main
    The scenes-app package serves as a basic template for building Grafana applications using the @grafana/scenes library. It provides a starting point for developers looking to create custom Grafana-based applications or plugins that leverage the Scenes framework for UI composition and state management.
  2. Overview of Grafana Scenes packages

    main

    Grafana Scenes is a framework designed to help you build highly interactive Grafana applications. The project is split into several key packages:

    • @grafana/scenes: The core Scenes SDK.
    • @grafana/scenes-react: React bindings for the Scenes framework.
    • scenes-app: A demo application that showcases the capabilities of the Scenes framework.
    • website: The project's documentation website.
  3. About @grafana/scenes

    main

    @grafana/scenes is a library designed to build highly interactive, dashboard-like experiences within Grafana app plugins. It provides built-in support for common dashboarding requirements, including:

    • Versatile layout options
    • Rendering Grafana panels
    • Querying and data transformations
    • Multiple time range support
    • Template variables support
    • URL synchronization
  4. Handle variable loading states with `sceneGraph.hasVariableDependencyInLoadingState`

    main

    When implementing logic that depends on variables (like a SceneQueryRunner), you should avoid executing actions while variables are still loading.

    Use sceneGraph.hasVariableDependencyInLoadingState(model) to check if any variable in the dependency chain is currently in a loading state. This function performs a deep check through the entire dependency tree.

    Best Practices for Complex Dependencies

    If your object subscribes to both time and variables, variables might change as a reaction to time changes. To avoid double reactions and ensure stability, use the following pattern:

    1. Use VariableDependencyConfig.
    2. Implement the onVariableUpdateCompleted callback. This callback is triggered whenever a dependency changes value or when the variable update process (including loading phases) is completed.
    3. Check hasVariableDependencyInLoadingState before issuing queries or heavy logic to skip execution while the dependency chain is resolving.

    This ensures that even if a variable doesn't change its value but merely completes its loading phase, your object is notified to proceed.

  5. How to share and filter query results between panels

    main

    You can share query results between multiple panels by placing a single SceneQueryRunner at a high level in the scene hierarchy.

    To display different subsets of that data in different panels, use a SceneDataTransformer at the individual panel level. You can filter the resulting DataFrame array by checking the refId property on each DataFrame to determine which query produced it.

  6. How SceneApp and SceneAppPage work together to build apps

    main

    To build a highly interactive Grafana app plugin using Scenes, you use two primary abstractions: SceneApp and SceneAppPage.

    • SceneApp is the root object that manages the entire application lifecycle, including routing and URL synchronization. It acts as the container for all your application's pages.
    • SceneAppPage represents an individual page within your app. It handles page-specific metadata (like titles and icons), routing (via url and routePath), navigation (via tabs and drilldowns), and the actual content to be rendered (via the getScene function).

    Workflow:

    1. Define your content using a getScene function that returns an EmbeddedScene.
    2. Wrap that content in a SceneAppPage configuration.
    3. Register the SceneAppPage in the pages array of a SceneApp instance.
    4. Render the SceneApp using the useSceneApp hook within your React plugin component.
    const getScene = () => new EmbeddedScene({ /* ... content ... */ });
    
    const myAppPage = new SceneAppPage({
      title: 'My Page',
      url: '/my-page',
      getScene,
    });
    
    const sceneApp = new SceneApp({
      pages: [myAppPage],
    });
  7. What are behaviors and how to use them

    main

    Behaviors allow you to implement custom scene logic as side effects. They are useful for tasks like conditionally hiding elements or attaching shared functionalities across different scene objects.

    To attach behaviors to a scene object, use the $behaviors state property. For example, you can attach them to a SceneQueryRunner or any other SceneObject.

    const queryRunner = new SceneQueryRunner({
      $behaviors: [
        /* list of behaviors */
      ],
    
      datasource: {
        type: 'prometheus',
        uid: 'gdev-prometheus',
      },
      queries: [
        {
          refId: 'A',
          range: true,
          format: 'time_series',
          expr: 'rate(prometheus_http_requests_total[5m])',
        },
      ],
    });
  8. Supported variable types in Grafana Scenes

    main

    Scenes support several types of variables to parameterize queries, panel titles, and custom scene objects:

    • QueryVariable: Generates a list of values from a query (e.g., metric names, server names).
    • DataSourceVariable: Defines a list of data sources of a specific type.
    • CustomVariable: Manually defined options using a comma-separated list.
    • ConstantVariable: A variable that holds a constant value.
    • TextBoxVariable: A free text input field with an optional default value.
  9. Handle Scene Object references and parenting

    main

    A scene object's parent is automatically set when it is added to the state of another object. Do not reuse the same instance of a scene object in multiple locations within a scene or across different scenes, as this will cause parentage conflicts.

    If you need to use the same object definition in multiple places, use one of these two patterns:

    1. Clone the object: Create a new instance using a clone method to ensure it has no connection to the original.
    2. Use SceneObjectRef: Wrap the instance in a SceneObjectRef. This allows you to store a reference to the instance in another object's state without changing the original object's parent.