Open-Source Wikis

/

Grafana

/

Backend

/

Plugins

grafana/grafana

Plugin host

The plugin host is responsible for discovering, loading, sandboxing, and dispatching to plugins. It lives across two trees:

Plugin types

Grafana supports three flavors of plugins:

  • Datasource plugin — provides a DataSource class (frontend) and optionally a DataSourceServer (backend). Returns DataFrames.
  • Panel plugin — frontend-only React component that renders a panel.
  • App plugin — bundles UI pages, custom routes, and may also include datasource/panel plugins.

A plugin can have:

  • A frontend module (TypeScript, bundled to module.js) — required for datasource and panel; optional for app.
  • A backend binary (Go using grafana-plugin-sdk-go) — required for datasource plugins that need server-side execution.

Layout

pkg/plugins/
├── plugins.go                 # Plugin model + interfaces
├── manager/                   # Lifecycle: install, start, stop, register
├── loader/                    # Discover & verify on disk
├── repo/                      # grafana.com plugin repository client
├── pipeline/                  # Plugin loading pipeline (steps)
├── pfs/                       # Plugin filesystem abstraction
├── plugindef/                 # plugin.json schema + decoder
├── backendplugin/             # gRPC client to subprocess plugins
├── envvars/                   # Per-plugin env var injection
├── auth/                      # Plugin auth helpers
├── log/                       # Plugin log capture
├── oauth/                     # OAuth token forwarding to plugins
├── plugincontext/             # Per-request context passed into plugins
├── storage/                   # Plugin disk paths
└── manager/sources/           # Bundled, gcom, registry sources

The companion DI layer:

pkg/services/pluginsintegration/
├── plugins.go                 # Wire-friendly aggregator
├── plugincontext/             # ReqContext → PluginContext
├── pluginerrs/                # Error types
├── pluginchecker/             # Periodic update checks
├── pluginsettings/            # Per-org plugin settings
├── pluginstore/               # Plugin registry storage
├── adapters/                  # Adapt new SDK to old internal interfaces
└── ... (~30 sub-packages)

Lifecycle

graph TD
    Boot[Server start] --> Discover[loader<br/>scan disk + registry]
    Discover --> Verify[Signature & manifest verify]
    Verify --> Register[manager<br/>Register in store]
    Register --> Backend[Start backend subprocess<br/>if any]
    Backend --> gRPC[Open gRPC channel]
    gRPC --> Ready[Plugin ready]
    Request[Datasource query] --> Dispatch[manager.Dispatch]
    Dispatch --> Lookup[Lookup plugin by id]
    Lookup --> Forward[Forward gRPC call]
    Forward --> Plugin[Plugin process]
    Plugin --> Forward
    Forward --> Response[Response back to client]

Bundled plugins (public/app/plugins/datasource/*, public/app/plugins/panel/*, and the matching pkg/tsdb/<name>/) are registered as in-process plugins; their backend "subprocess" is just a Go function call.

External plugins discovered in data/plugins/ (or wherever [plugins] plugins_path points) are launched as separate processes that communicate over gRPC. The plugin host enforces signature verification per [plugins] allow_loading_unsigned_plugins.

Frontend loading

The frontend has its own loader in public/app/features/plugins/:

  • plugin_loader.ts resolves a plugin's module.js and runs it.
  • pluginPreloader.ts warms up apps marked auto_enabled_apps.
  • sandbox/ runs untrusted plugin code inside an iframe with a restricted DOM API. Toggleable via the pluginsFrontendSandbox feature flag.
  • The dynamic import() of a plugin returns its exported Plugin object (new DataSourcePlugin(...).setQueryEditor(...).setConfigEditor(...)).

Plugin context

Each call into a plugin receives a PluginContext (pkg/plugins/plugincontext/) carrying:

  • The user identity (user.SignedInUser).
  • The datasource instance settings (URL, jsonData, decrypted secureJsonData).
  • The plugin instance settings (per-org pluginsettings).
  • A request scope (orgID, requestID).

Backend plugins use this to authenticate to upstream systems (e.g. inject the configured Bearer token) and to scope responses.

Error handling

Plugin failures are first-class — errors are wrapped with pluginerrs types and surfaced to the UI as red error banners on panels. Common failure modes:

  • signature: invalid — failed signature check.
  • dependency: missing — plugin requires a Grafana version > installed.
  • Backend rpc error — subprocess crashed or didn't respond.

The plugin admin UI (public/app/features/plugins/admin/) shows install/update/error state per plugin.

Update checks

pkg/services/pluginsintegration/pluginchecker/ periodically queries grafana.com for new versions of installed plugins. The "Updates" tab in the plugins UI is driven by this.

Key source files

File Purpose
pkg/plugins/plugins.go Core plugin types
pkg/plugins/manager/manager.go Plugin lifecycle
pkg/plugins/loader/loader.go Discovery + load pipeline
pkg/plugins/backendplugin/ gRPC dispatch
pkg/plugins/plugindef/ plugin.json schema
pkg/services/pluginsintegration/plugins.go DI aggregator
public/app/features/plugins/plugin_loader.ts Frontend loader
public/app/features/plugins/sandbox/ iframe sandbox

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Plugins – Grafana wiki | Factory