Grafana

Grafana is a visualisation and query front end. It stores no telemetry of its own; it queries data sources — Prometheus, Loki, Tempo, CloudWatch, SQL databases and many more — and renders the results as dashboards. Its value is putting data from different systems side by side on one time axis.

Core concepts

ConceptMeaning
Data sourceA connection to a backend plus the query editor for its language
PanelOne visualisation driven by one or more queries
DashboardA set of panels with a shared time range and variables
VariableA dropdown whose value is substituted into queries: cluster, namespace, service
FolderGroups dashboards and carries permissions
ExploreAn ad hoc query view for investigation, without building a dashboard
Alert ruleA query evaluated on a schedule that fires when a condition holds

Dashboards that answer questions

Most dashboards fail because they are a wall of graphs with no argument. A useful one is built top-down:

  1. Row one: is it healthy? A few stat panels for the service’s key indicators — request rate, error ratio, latency percentile, saturation. Someone should be able to tell good from bad in five seconds.
  2. Row two: where is the problem? The same signals broken down by the most useful dimension: endpoint, dependency, zone, version.
  3. Row three and below: why? Resources, runtime internals, dependencies. Collapsed by default.

Practical rules:

  • One dashboard per service or per question, not one per metric source.
  • Use the RED and USE layouts consistently so every service’s dashboard reads the same way. The signals come from instrumentation.
  • Show percentiles, not averages, for latency.
  • Fix the y-axis where it matters: an error-ratio panel that auto-scales makes 0.01% look as alarming as 10%.
  • Units and thresholds on every panel. Draw the objective as a line.
  • Annotate deployments. Vertical markers at release times explain half of all step changes.
  • Link, do not cram. Add drill-down links from an overview to detail dashboards instead of fitting everything on one screen.

Variables

Name:   namespace
Type:   Query
Query:  label_values(kube_pod_info{cluster="$cluster"}, namespace)
sum by (pod) (
  rate(container_cpu_usage_seconds_total{cluster="$cluster", namespace="$namespace"}[$__rate_interval])
)
  • Chain variables (cluster → namespace → workload) so each narrows the next.
  • Use $__rate_interval rather than a hard-coded [5m]. It adapts to the zoom level and the scrape interval, which avoids empty or misleading rate() results. The query language itself is covered in PromQL.
  • A multi-value variable needs a regex matcher: namespace=~"$namespace".

Dashboards as code

Dashboards edited by hand in the UI drift, get broken by a well-meant change, and vanish with the instance. Keep them in Git.

ApproachHow
File provisioningJSON files mounted into Grafana; on Kubernetes, a sidecar loads ConfigMaps with a label
Grafana OperatorGrafanaDashboard and GrafanaDatasource custom resources
Terraform providerDashboards, folders, data sources and alert rules as Terraform resources
Generated JSONGrafonnet (Jsonnet) or the Foundation SDK to build many consistent dashboards from code
Git syncGrafana’s built-in two-way synchronisation with a repository
apiVersion: v1
kind: ConfigMap
metadata:
  name: checkout-dashboard
  labels:
    grafana_dashboard: "1" # picked up by the dashboard sidecar
data:
  checkout.json: |
    { "title": "Checkout", "uid": "checkout", "panels": [ ... ] }

Set a stable uid so links survive re-imports, and mark provisioned dashboards read-only so UI edits cannot silently diverge. Provision data sources the same way, with credentials from a secret store rather than typed into the UI — see infrastructure as code.

Correlating signals

The reason to run metrics, logs and traces behind one front end is moving between them without retyping context:

latency panel ──(exemplar)──► trace in Tempo ──(trace to logs)──► log lines in Loki
      ▲                                                                │
      └──────────────(derived field: trace_id in a log line)◄──────────┘
  • Exemplars on a histogram panel are dots that link to a concrete trace.
  • Trace to logs / trace to metrics are configured on the tracing data source and need consistent labels (service, namespace, pod) across all three backends.
  • Derived fields on the logs data source turn a trace_id in a log line into a link.

This only works if the telemetry shares identifiers, which is what semantic conventions and context propagation provide. The backends are described in the LGTM stack.

Alerting

Grafana has its own alerting engine: rules query any data source, including several in one rule, and notifications go through contact points and notification policies that mirror Alertmanager’s routing tree.

Prometheus rules + AlertmanagerGrafana alerting
Data sourcesPrometheus-compatible onlyAny, and combinations
Where rules liveNext to the metrics, evaluated by the storeIn Grafana
Survives Grafana being downYesNo
Managed as codeRule filesProvisioning files, Terraform, the API

For Prometheus metrics, keep paging rules in Prometheus or Mimir so alerting does not depend on the dashboard server. Use Grafana alerting for conditions that span sources, such as logs or SQL. Alert design is in alerting.

Access and operations

  • Authentication through OIDC or SAML against the organisation’s identity provider; map groups to roles. Background: authentication.
  • Permissions by folder: teams edit their own folder, view the rest.
  • Data source permissions matter more than dashboard permissions — anyone who can use Explore can query everything the data source can read.
  • State lives in a database. Use PostgreSQL or MySQL rather than the default SQLite for anything shared, and run more than one replica.
  • Managed options — Grafana Cloud, Amazon Managed Grafana, Azure Managed Grafana — remove the operational work at the cost of some plugin freedom.

Common mistakes

MistakeEffect
A panel per metric, no hierarchyNobody can tell what matters
Hundreds of dashboards, nobody owns themPeople stop trusting any of them
Queries over long ranges without recording rulesSlow dashboards and a loaded metrics backend
Auto-refresh at 5 seconds on a wall displayConstant query load for no benefit
Different label names per teamVariables and correlations break
Copying a community dashboard unmodifiedHalf the panels show “No data” because labels differ

Delete dashboards. Grafana’s usage insights show which ones nobody opens.

Further reading