Grafana: Dashboards & visualization

This section documents the current Prometheus 3.x line (latest 3.14.0) as published at the Prometheus documentation and the current Grafana 13.x line (latest 13.2.1) as published at the Grafana documentation, which are the references these pages are written and verified against. No specific patch version is pinned. Some capabilities (Grafana Enterprise-only features, Grafana Cloud-hosted services, and long-term-storage systems like Thanos/Cortex/Mimir) are linked, not documented in depth.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production, since both projects iterate quickly.

This section’s bibliography lists the reference material consulted while preparing these pages.

Prometheus stores and evaluates time series; it does not itself build dashboards — the expression browser’s Graph tab is deliberately minimal, meant for ad-hoc queries rather than a shared operational view. Grafana is the visualization layer almost every Prometheus deployment sits behind: it queries Prometheus (and other backends) over HTTP, arranges the results into panels on a dashboard, and lets those dashboards be parameterized and shared. This page covers installing Grafana, connecting it to a Prometheus server, the panel types a dashboard is built from, and template variables that make one dashboard work across many jobs or instances.

Installing Grafana

Grafana ships as a binary package, a Docker image, or an OS package, and always listens on :3000 with a default admin/admin login that it forces you to change on first sign-in. See Install Grafana for every installation method and platform in full, including the Windows and macOS installers not shown here.

Docker

The official image is published as grafana/grafana-oss (open-source edition) on Docker Hub. Publish port 3000 and bind-mount a volume so dashboards and users survive a container restart:

docker run -d --name grafana -p 3000:3000 \
  -v grafana-storage:/var/lib/grafana \
  grafana/grafana-oss
# http://localhost:3000, default login admin/admin
# https://grafana.com/docs/grafana/latest/setup-grafana/installation/

Package manager / binary

On Debian/Ubuntu, Grafana’s own APT repository installs and manages the service:

sudo apt-get install -y apt-transport-https software-properties-common
sudo mkdir -p /etc/apt/keyrings/
wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update && sudo apt-get install -y grafana
sudo systemctl enable --now grafana-server
# https://grafana.com/docs/grafana/latest/setup-grafana/installation/

The standalone binary archive (no root, no service manager) works the same way as Prometheus’s own tarball install described in Getting Started: extract it and run ./bin/grafana server from the extracted directory. Whichever method is used, the first sign-in at http://localhost:3000 prompts for a new admin password before anything else is usable.

Adding the Prometheus data source

A data source tells Grafana where to send queries. Prometheus is a first-class data source type — its query editor understands PromQL directly, including autocomplete against the metrics and labels the target server actually has. See Prometheus data source for every configuration field.

Via the UI

Connections > Data sources > Add data source > Prometheus, then set the Prometheus server URL (http://localhost:9090 for a local server, or the in-cluster service DNS name when both run in Kubernetes) and Save & test. Grafana confirms the connection by querying the target’s /api/v1/query endpoint before saving.

Via provisioning

Clicking through the UI does not survive a redeployed container or a fresh environment. Grafana reads any YAML file dropped into provisioning/datasources/ at startup and creates or updates data sources from it — the infrastructure-as-code equivalent of the UI form above:

apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    jsonData:
      httpMethod: POST
      timeInterval: 15s
# https://grafana.com/docs/grafana/latest/datasources/prometheus/

access: proxy routes the browser’s query through the Grafana server rather than calling Prometheus directly from the client — the setting almost every deployment wants. Mount this file at /etc/grafana/provisioning/datasources/prometheus.yaml in the Docker image above (or the Kubernetes-native equivalent, a ConfigMap) and it is present on every container start with no manual step; dashboards can be provisioned the same way, covered next.

Dashboards and panel types

A dashboard is a grid of panels, each running its own query (or queries) against a data source and rendering the result with a chosen visualization. See Dashboards for creating, organizing, and sharing them, and Panels & visualizations for the full visualization catalog beyond the five below.

Panel type When to use it

Time series

The default choice for anything with a meaningful time axis — request rate, latency, memory over time. Plots one or more series as lines or bars against wall-clock time; the panel most Prometheus dashboards are built from.

Stat

A single current number, optionally with a sparkline and threshold-driven color — "requests per second right now," "error rate this hour." Reduces a query down to one value per series rather than plotting a time axis.

Gauge

The same single-value reduction as Stat, drawn as an arc against a min/max range — best when the position within a bounded range matters more than the raw number, such as disk usage approaching 100%.

Table

Tabular results — one row per label combination, one column per field — for browsing raw series values or an instant-vector query’s full label set rather than a trend.

Bar gauge

Like Gauge but one bar per series instead of one arc for the whole panel — comparing a bounded value (queue depth against a configured max, disk usage) across many instances or jobs at once.

Panels compose into a dashboard through Grafana’s own editor — drag to resize, add a panel, pick its visualization and query — but every dashboard is, underneath, one JSON document (the dashboard model): panels, their queries, layout, and variables as a single serializable object. Building through the UI and hand-editing (or generating) that JSON are two views of the same thing, and both remain fully compatible — a dashboard built by hand can be exported to JSON for version control, and a JSON file authored or generated elsewhere (a provisioning pipeline, a dashboard shared from Grafana’s public dashboard library) imports and edits in the UI exactly like one built there from scratch. Provisioning dashboards from files works the same way as the data source YAML above, via provisioning/dashboards/ pointing at a directory of these JSON files, so a dashboard ships with its data source rather than being recreated by hand in each environment.

Template variables

A dashboard hard-coded to one job or instance only ever shows that one target. A template variable turns part of a panel’s query into a dropdown the viewer picks from, so one dashboard serves every job, instance, or namespace scraped by Prometheus. See Variables for every variable type beyond the query-backed one below.

A query-type variable, backed by Prometheus’s label_values() helper, lists every distinct value a label takes across a metric (or across the whole TSDB, if the metric argument is omitted):

label_values(up, instance)

Define instance as a dashboard variable with that query, enable Multi-value and Include All if every target should be selectable at once, and reference it from a panel’s PromQL with $instance (or ${instance} where the surrounding syntax needs braces):

up{instance=~"$instance"}

=~ is required, not =, because a multi-value selection expands to a regex alternation ("web-1|web-2") rather than a single string — the same regex matcher covered in PromQL: Basics & Selectors. Variables can also chain: a job variable’s label_values() query can itself be scoped so a dependent instance variable only lists instances belonging to the currently selected job, keeping large multi-team dashboards navigable instead of listing every instance in the cluster at once.

Continue with Grafana Alerting for alerting rules defined and evaluated inside Grafana itself, as distinct from the Prometheus-side rules covered in Recording & Alerting Rules and routed by Alertmanager.

For Grafana dashboards of Apache JMeter load-test metrics next to these server metrics, see Real-time Monitoring with Backend Listener.