Experimental: This plugin is experimental. Features may be incomplete or have known limitations, and you should expect some rough edges. See Experimental Status for details.
Connect Grafana to Cube for semantic layer analytics. Query measures and dimensions, apply filters, and visualize your data—without writing SQL.
Try it live on play.grafana.org →
This plugin brings a true semantic layer to Grafana for the first time. By connecting to Cube, you get:
- No more writing SQL — Query your data using pre-defined measures and dimensions
- No more writing JOINs — Cube handles the complexity of joining tables for you
- Single source of truth — Business metrics are defined once in Cube and used consistently across all dashboards
- Lower barrier to entry — Non-technical users can build dashboards without SQL knowledge
- Scalable complexity — Start simple, but analytics queries can grow as sophisticated as you need
- More maintainable dashboards — Panels require far less code when using semantic definitions
- Cross-panel filtering — Use AdHoc filters to drill down across Table and Bar Chart panels, enabling data exploration for dashboard viewers
The visual query builder supports:
| Feature | Description |
|---|---|
| Dimensions | Select one or more dimensions to group your data |
| Measures | Select one or more measures to aggregate |
| Limit | Control the number of rows returned (defaults to 10,000; maximum 50,000). See Cube's row limit documentation for details. |
| Filters | Filter your query before aggregation |
| Order | Sort results by any selected dimension or measure |
The visual query builder supports:
- Filter members: Dimensions only
- Operators:
equalsandnotEquals, each accepting multiple values - Multiple filters: Combine with AND (intersection)
The full Cube filter syntax is supported when editing queries via the panel JSON editor, including:
- All Cube filter operators:
contains,gt,gte,lt,lte,set,notSet,inDateRange, and more - Measure filters: Filter on any measure, not just dimensions
- AND/OR filter groups: Combine filters with logical AND/OR for complex conditions (e.g. "status = completed OR payment_method = credit_card")
Queries using these features display in the read-only JSON viewer (see below). The visual builder includes a hint with a link to the Cube filter docs for reference.
When a query uses features that the visual builder cannot represent (such as time dimensions configured in the panel JSON), the editor automatically switches to a read-only JSON viewer. This shows:
- An info banner explaining which features triggered JSON mode
- The full query as syntax-highlighted JSON
- A compiled SQL preview
This ensures no query configuration is hidden — users always see exactly what is configured, even for advanced queries. To edit these queries, use the dashboard JSON editor or panel JSON editor.
Clicking a value in a Table or Bar Chart panel creates or updates an AdHoc dashboard variable scoped to the Cube datasource. This enables powerful cross-panel filtering and data exploration.
AdHoc filters can also be edited directly in the dashboard UI to add additional filter members, operators, and values. The same operator limitations apply (= and != only).
How filters combine:
- Multiple AdHoc filters combine with AND (intersection)
- AdHoc filters combine with per-panel filters using AND (intersection)
To filter all panels by the dashboard time picker:
- Create a dashboard variable with identifier
cubeTimeDimension - Set its value to the time dimension field you want to filter by (e.g.,
order_date) - The dashboard's
$__fromand$__tovariables will automatically apply to all panels
This plugin is experimental. Current limitations include:
| Limitation | Details |
|---|---|
| Cube Cloud authentication | Authentication does not yet work with Cube Cloud. Self-hosted Cube (dev and production mode) works correctly. |
| Technical field names | Dimension and measure names currently use full technical identifiers (e.g., orders.customer_name) rather than human-readable labels. This is due to a dependency on how Grafana implements AdHoc filters. |
| Visual builder filter operators | The visual builder only supports equals and notEquals. All Cube operators are available via panel JSON. |
| Visual builder filter members | The visual builder only supports dimension filters. Measure filters are available via panel JSON. |
| Cross-panel filtering | Depends on Grafana AdHoc filters. Currently works with Table and Bar Chart panels only |
Not for production use. This plugin is experimental and is not meant to be used in production or critical environments.
This plugin is marked as experimental, meaning:
- Features may be incomplete or have known limitations
- Backward compatibility is not guaranteed between versions
- The data model, configuration, or UI might change, potentially breaking dashboards
- The risks are unknown and potentially high
- Support is limited to GitHub issues; no SLA is provided
Do not use this plugin in production environments. It is intended for:
- Testing and evaluation
- Development environments
- Providing early feedback
- Validating use cases before production readiness
Track the CHANGELOG for breaking changes and stability updates.
Cube is a semantic layer that sits between your data warehouse and your applications. It provides a consistent API for querying data, handles caching, security, and pre-aggregations. This Grafana plugin enables you to leverage Cube's powerful data modeling capabilities directly in your Grafana dashboards.
-
Install dependencies
npm install
-
Update Grafana plugin SDK for Go dependency to the latest minor version:
go get -u github.com/grafana/grafana-plugin-sdk-go go mod tidy
This plugin backend is written in Go, but Cube protocol semantics are primarily
defined by Cube's JavaScript SDK (@cubejs-client/core) and Cube REST docs.
When changing protocol-level behavior (for example /v1/load handling, retry
behavior, timeout/cancellation semantics, status/error mapping, progress fields):
- Check Cube JS SDK behavior first (local path:
../cube/packages/cubejs-client-core/src/index.ts) - Check Cube REST docs (local path:
../cube/docs/pages/product/apis-integrations/rest-api.mdx) - Mirror SDK behavior by default unless there is a clear Grafana/backend reason to diverge
- If intentionally diverging, document rationale and user impact in the PR and add tests that explicitly cover the divergence
For the best development experience with automatic reloading of both frontend and backend changes:
Terminal 1 - Frontend Development:
npm run devTerminal 2 - Backend Development with Auto-reload:
DEVELOPMENT=true docker compose up --buildThis setup provides:
- Frontend hot-reloading: Changes to TypeScript/React code automatically refresh the browser
- Backend auto-rebuilding: Changes to Go code automatically rebuild and reload the plugin
- Built-in debugging: Delve debugger available on port 2345
The docker-compose setup includes Cube and Postgres with sample data, starting:
- Postgres with JaffleShop sample data pre-loaded
- Cube connected to Postgres
- Grafana with the plugin loaded
Once running, you can:
-
Access Grafana at: http://localhost:3000
- Login with username:
admin, password:admin - The Cube datasource is automatically provisioned and ready to use
- A PostgreSQL datasource is also provisioned for direct database access
- Sample dashboards are pre-loaded for testing
- Login with username:
-
Test the Cube API directly (authentication is not required):
curl -G --data-urlencode 'query={"dimensions":["order_details.customers_first_name"],"measures":["order_details.payments_total_amount","order_details.count"]}' http://localhost:4000/cubejs-api/v1/load | jq '.data[0]'
For production builds or manual development:
Backend builds:
# Build for all platforms
mage -v
# Build for M4 Mac (ARM64 Linux)
mage -v build:linuxARM64
# List all available Mage targets
mage -lFrontend builds:
# Production build
npm run build
# Alternative Docker setup (without auto-reload)
npm run serverTesting:
# Run unit tests with file watching
npm run test
# Run unit tests once (for CI)
npm run test:ci
# Run E2E tests (using Playwright)
# First, spin up a Grafana instance to test against:
npm run server
# Optionally specify Grafana version (recommended dev target):
GRAFANA_VERSION=12.3.3 npm run server
# Validate minimum supported version compatibility:
GRAFANA_VERSION=12.2.5 npm run server
# Then run the E2E tests:
npm run e2eCode Quality:
# Run linter
npm run lint
# Auto-fix linting issues
npm run lint:fixThis plugin uses Grafana's standardized CI/CD workflows for automated building, testing, and publishing.
The CI pipeline automatically:
- Builds and tests the plugin on every push and PR
- Creates signed ZIP files for all supported platforms
- Uploads artifacts to GitHub Actions and GCS storage
- Runs E2E tests using Playwright
Q: Does the CI pipeline produce a signed plugin ZIP?
A: Yes, the CI automatically builds and signs ZIP files for all platforms (universal + per-architecture for the Go backend).
Q: Where are the ZIP files uploaded?
A: ZIP files are uploaded to:
- GitHub Actions artifacts (for PRs and development)
- GCS storage (for release artifacts)
Q: How can I use these ZIPs on Grafana Cloud?
A: For Grafana Cloud deployment, use the "Plugins - CD" workflow in the Actions tab to publish to dev/ops/prod environments.
This repository uses a three-workflow release pipeline:
release-please.yml— Runs on every push tomain. Maintains an open "Release Please" PR that bumps the npm version and prepends aCHANGELOG.mdentry from conventional commits since the last tag. Merging the PR creates the version commit onmainand pushes the new tag.release.yml— Triggered automatically by the tag push. Builds and signs the plugin for all platforms, creates a draft GitHub release with the artifacts, SHA checksums, and provenance attestation.publish.yaml("Plugins - CD") — Manual workflow that publishes to the Grafana Cloud plugin catalog (dev / ops / prod-canary / prod).
The version bump and tag step happens entirely in CI — no local git or npm commands are required.
We want GitHub releases with downloadable artifacts to be available as soon as a version is tagged, regardless of whether it's published to the Grafana catalog. This allows:
- QA and testers to download and verify the plugin before catalog publishing
- Transparency about what version exists, even if only deployed to dev/ops
- A clear audit trail of all released versions
The standard plugin-ci-workflows only creates GitHub releases when publishing to prod. Our release.yml fills this gap by creating releases on any tag push.
PR titles must use conventional commit prefixes (feat:, fix:, chore:, …) — enforced by the Conventional Commits check on every PR. The prefix decides which CHANGELOG.md section the change is filed under, and the same convention drives the SemVer bump:
While the plugin is pre-1.0, bump-minor-pre-major is set in release-please-config.json, so:
feat!:orBREAKING CHANGE:→minor(will bemajoronce 1.0 ships)feat:→patch(will beminoronce 1.0 ships)- Only
fix:/chore:/docs:etc. →patch
To cut a release, merge the open "chore(main): release X.Y.Z" pull request that the Release Please workflow keeps in sync on every push to main. Merging it commits the version bump and updated CHANGELOG.md to main and pushes the new tag — which triggers release.yml to produce a draft GitHub release ready for review and publishing.
If no release PR is open (e.g. nothing release-worthy has landed since the last tag), you can re-run Release Please manually:
gh workflow run release-please.ymlTo publish the plugin to the Grafana catalog:
- Go to Actions → "Plugins - CD" → "Run workflow"
- Choose target environment:
dev,ops,prod-canary, orprod - The workflow will build, sign, and publish automatically
You can deploy any branch (not just main) to test changes before merging:
Why: This lets you test your feature in a real Grafana Cloud environment before merging to main, catching integration issues early.
How:
- Set branch to your feature/PR branch name (e.g.,
feature/new-query-builder) - Set environment to
dev(safe testing environment) - Plugin version becomes
x.y.z+COMMIT_SHA(e.g.,1.2.3+a1b2c3d4)
Result: Your exact commit gets deployed to Grafana Cloud dev with a unique version identifier, allowing safe testing without affecting other developers or environments.
This section is for developers outside Grafana Labs who want to fork this repository and distribute their own version independently.
The GitHub Actions workflows in this repository (push.yaml and publish.yaml) are designed for Grafana's internal infrastructure and will not work for external contributors.
If you're forking this repo, you should:
- Revert to the previous CI workflows that come with a newly bootstrapped plugin - these contain the basic build, test, and packaging logic without Grafana-specific deployment steps
- Use manual plugin signing for distribution to your own Grafana instances
For private distribution or local development:
npm install -g @grafana/sign-plugin
npx @grafana/sign-plugin --rootUrls https://your-grafana-instance.comThis allows you to sign and distribute your fork without going through Grafana's official plugin catalog or internal infrastructure.
Below you can find source code for existing app plugins and other related documentation.

