Stage 6 · Operate
Dashboards with Grafana
Dashboards as Code
Managing dashboards with JSON models, Grafonnet, Terraform provider, and provisioning files.
Why Dashboards as Code?
Manually created dashboards drift between environments, cannot be reviewed in pull requests, and are difficult to replicate. Dashboards as code treats dashboard configuration as source code that is version-controlled, tested, and deployed through pipelines.
- Dashboards are version-controlled in Git alongside application code.
- Changes go through pull requests and code review.
- Dashboards are deployed automatically through CI/CD pipelines.
- Environment-specific overrides are managed through configuration.
JSON Model
Every Grafana dashboard is a JSON document. You can export dashboards as JSON from the UI and store them in Git. The JSON model defines panels, queries, variables, and layout. This is the simplest dashboards-as-code approach.
{
"dashboard": {
"title": "Service Overview",
"panels": [
{
"title": "Request Rate",
"type": "timeseries",
"targets": [
{
"expr": "sum(rate(http_requests_total[5m]))",
"legendFormat": "QPS"
}
]
}
],
"templating": {
"list": [
{
"name": "job",
"type": "query",
"query": "label_values(http_requests_total, job)"
}
]
}
}
}Grafonnet
Grafonnet is a Jsonnet library for Grafana dashboards. It provides high-level abstractions for panels, variables, and layouts. Grafonnet reduces boilerplate and enforces consistent dashboard structure across teams.
local grafana = import 'grafonnet/grafana.libsonnet';
local dashboard = grafana.dashboard;
local prometheus = grafana.prometheus;
local graphPanel = grafana.graphPanel;
dashboard.new(
'Service Overview',
tags=['service', 'production'],
time_from='now-1h',
)
.addPanel(
graphPanel.new(
'Request Rate',
datasource='Prometheus',
format='reqps',
).addTarget(
prometheus.target(
'sum(rate(http_requests_total[5m]))',
legendFormat='QPS',
),
),
gridPos={ x: 0, y: 0, w: 12, h: 8 },
)Terraform Provider
The Grafana Terraform provider manages dashboards as Terraform resources. It creates, updates, and deletes dashboards through the Grafana API. Combine it with Terraform's workspace feature to manage per-environment dashboards.
resource "grafana_dashboard" "service_overview" {
config_json = jsonencode({
title = "Service Overview"
tags = ["service", "production"]
templating = {
list = [{
name = "job"
type = "query"
query = "label_values(http_requests_total, job)"
}]
}
panels = [
{
title = "Request Rate"
type = "timeseries"
targets = [{
expr = "sum(rate(http_requests_total{job=~"$job"}[5m]))"
legendFormat = "QPS"
}]
}
]
})
}Provisioning Files
Grafana can load dashboards from JSON files on startup using provisioning. Place dashboard JSON files in the provisioning directory and reference them in the provisioning configuration. This is the simplest approach for single-instance deployments.
apiVersion: 1
providers:
- name: "Services"
orgId: 1
folder: "Services"
type: file
disableDeletion: false
editable: true
updateIntervalSeconds: 30
options:
path: /var/lib/grafana/dashboards/services
foldersFromFilesStructure: trueVersion Control Strategy
- Store all dashboard definitions in a dedicated observability repository.
- Organize by team or service in directory structure.
- Use environment-specific overlays for production vs staging.
- Automate dashboard deployment through CI/CD pipelines.
- Review dashboard changes with the same rigor as code changes.
If you have manually created dashboards, export them as JSON from the Grafana UI. Store the JSON in Git and manage it from there. This gives you an immediate audit trail and rollback capability.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.