Grafana is an open source tool for dashboards and alerts. Teams use it to explore metrics, logs, and traces from many data sources.
The Grafana plugin brings that context into Backstage. It shows dashboards related to a service. It lists recent alerts for that service. You can embed an overview dashboard on the entity page. The plugin maps dashboards and alerts to entities through simple annotations. You can match by tags or alert labels. The result is less tab switching and faster triage.
Common use cases are clear. Give service owners a quick health view during standups. Help on call engineers jump to the right panels. Share a standard overview across teams. Keep context while you debug and review incidents.
Grafana Labs also maintains a Backstage integration for Grafana Cloud Service Center. It reads your Backstage catalog to link services with incident and SLO data. As they describe it, “Users of Backstage can continuously import their Backstage catalog to populate Service Center data in Grafana Cloud.”
If you run a self hosted Backstage, this plugin puts Grafana where your engineers already work. It keeps the catalog and your operational reality in sync.
Installation Instructions
These instructions apply to self-hosted Backstage only. To use this plugin on Roadie, visit the docs.
Install the frontend package
cd packages/app
yarn add @k-phoen/backstage-plugin-grafana
Expose the plugin in your frontend
// packages/app/src/plugins.ts
export { grafanaPlugin } from '@k-phoen/backstage-plugin-grafana';
Configure the proxy and plugin settings
Add a proxy route and Grafana settings in app-config.yaml. Use an API token with Viewer access.
# app-config.yaml
proxy:
'/grafana/api':
target: https://grafana.host/
headers:
Authorization: Bearer ${GRAFANA_TOKEN}
grafana:
domain: https://monitoring.company.com
unifiedAlerting: false
Set GRAFANA_TOKEN in your runtime environment.
Enable the backend proxy on the old backend system
Install the backend proxy plugin
yarn workspace backend add @backstage/plugin-proxy-backend
Create the proxy plugin file
// packages/backend/src/plugins/proxy.ts
import { createRouter } from '@backstage/plugin-proxy-backend';
import { PluginEnvironment } from '../types';
export default async function createPlugin(env: PluginEnvironment) {
return await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
tokenManager: env.tokenManager,
httpAuth: env.httpAuth,
});
}
Wire it in the backend
// packages/backend/src/index.ts
import proxy from './plugins/proxy';
// other imports...
async function main() {
// existing setup...
const apiRouter = Router();
const env = useHotMemoize(module, () => createEnv('proxy'));
apiRouter.use('/proxy', await proxy(env));
app.use('/api', apiRouter);
// existing startup...
}
main().catch(err => {
process.exit(1);
});
Enable the backend proxy on the new backend system
Install the backend proxy plugin
yarn workspace backend add @backstage/plugin-proxy-backend
Register the proxy plugin
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
import { proxyPlugin } from '@backstage/plugin-proxy-backend';
const backend = createBackend();
backend.add(proxyPlugin());
backend.start();
Show dashboards on the entity page
Import the dashboards card and add it to the entity page
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import Grid from '@material-ui/core/Grid';
import {
EntityAboutCard,
EntityLinksCard,
EntityHasSubcomponentsCard,
} from '@backstage/plugin-catalog';
import {
EntityGrafanaDashboardsCard,
} from '@k-phoen/backstage-plugin-grafana';
export const overviewContent = (
<Grid container spacing={3} alignItems="stretch">
<Grid item md={6}>
<EntityAboutCard variant="gridItem" />
</Grid>
<Grid item md={6}>
<EntityGrafanaDashboardsCard />
</Grid>
<Grid item md={4} xs={12}>
<EntityLinksCard />
</Grid>
<Grid item md={8} xs={12}>
<EntityHasSubcomponentsCard variant="gridItem" />
</Grid>
</Grid>
);
Add a selector to your entity to link dashboards
# catalog-info.yaml
metadata:
annotations:
grafana/dashboard-selector: "(tags @> 'my-service' || tags @> 'my-service-slo') && tags @> 'generated'"
You can also use a short selector
metadata:
annotations:
grafana/dashboard-selector: my-service
Supported variables
- title
- tags
- url
- folderTitle
- folderUrl
Supported binary operators
- ||
- &&
- ==
- !=
- @>
Supported unary operators
- !
Show alerts on the entity page
Import the alerts card and add it to the entity page
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import Grid from '@material-ui/core/Grid';
import {
EntityAboutCard,
EntityLinksCard,
EntityHasSubcomponentsCard,
} from '@backstage/plugin-catalog';
import {
EntityGrafanaAlertsCard,
} from '@k-phoen/backstage-plugin-grafana';
export const overviewContent = (
<Grid container spacing={3} alignItems="stretch">
<Grid item md={6}>
<EntityAboutCard variant="gridItem" />
</Grid>
<Grid item md={6}>
<EntityGrafanaAlertsCard />
</Grid>
<Grid item md={4} xs={12}>
<EntityLinksCard />
</Grid>
<Grid item md={8} xs={12}>
<EntityHasSubcomponentsCard variant="gridItem" />
</Grid>
</Grid>
);
If Grafana unified alerting is enabled
# catalog-info.yaml
metadata:
annotations:
grafana/alert-label-selector: "service=awesome-service"
If Grafana legacy alerting is used
# catalog-info.yaml
metadata:
annotations:
grafana/tag-selector: "my-tag"
Embed an overview dashboard on the entity page
Import the viewer and add it to the entity page
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import Grid from '@material-ui/core/Grid';
import {
EntityAboutCard,
EntityLinksCard,
EntityHasSubcomponentsCard,
} from '@backstage/plugin-catalog';
import {
EntityOverviewDashboardViewer,
} from '@k-phoen/backstage-plugin-grafana';
export const overviewContent = (
<Grid container spacing={3} alignItems="stretch">
<Grid item md={6}>
<EntityAboutCard variant="gridItem" />
</Grid>
<Grid item md={6}>
<EntityOverviewDashboardViewer />
</Grid>
<Grid item md={4} xs={12}>
<EntityLinksCard />
</Grid>
<Grid item md={8} xs={12}>
<EntityHasSubcomponentsCard variant="gridItem" />
</Grid>
</Grid>
);
Add the dashboard URL to the entity
# catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-entity
annotations:
grafana/overview-dashboard: 'http://grafana/d/qSfS51a4z/some-dashboard?orgId=1&kiosk'
spec: {}
Grafana must allow embedding. Update grafana.ini if needed.
# grafana.ini
[security]
allow_embedding = true
[session]
cookie_samesite = none
Only change these settings if you understand the impact.
Use the generic dashboard viewer
You can embed any dashboard with a fixed URL. Add this where you want it to render.
// packages/app/src/components/somewhere/GrafanaDashboardSection.tsx
import React from 'react';
import { DashboardViewer } from '@k-phoen/backstage-plugin-grafana';
export const GrafanaDashboardSection = () => (
<DashboardViewer
height={800}
url="https://monitoring.company.com/d/abc123/my-dashboard?orgId=1&kiosk"
/>
);
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.