Build a Grafana Dashboard

Build a Grafana dashboard for metrics — Linux · networking · telemetry.

Focus: build a grafana dashboard for metrics

Sponsored

You've spent days configuring exporters, wiring up Prometheus scrape jobs, and staring at raw metric endpoints — but when your manager asks "how's the system doing?", you still can't answer without a terminal and a prayer. That's the problem this lesson solves: raw telemetry is data, not insight. By building a Grafana dashboard for metrics, you turn scattered time series into a living, at-a-glance view of your Linux hosts and network — the difference between monitoring and actually seeing what's happening.

The problem this lesson solves

Raw metrics are noisy. A single host can expose hundreds of series: CPU idle ticks, memory fragmentation, TCP retransmits, disk I/O latencies. Even with Prometheus querying, you're stuck writing ad-hoc queries in a browser — slow, error-prone, and impossible to share. Dashboards give your team a single pane of glass, but poorly built dashboards are just as bad: too many metrics, clashing units, no context, and nobody dares change a panel. This lesson teaches you to build a Grafana dashboard for metrics that's useful — focused on your questions, not just your data.

Core concept / mental model

Think of a Grafana dashboard as a control room, not a data dump. Every panel answers a question: Is the disk filling? Are we dropping packets? Is the API latency climbing? The dashboard is your mental model of the system — laid out left to right, top to bottom, like reading a story: start with broad health, drill into specific subsystems.

  • Data source — where the metrics live (Prometheus, InfluxDB, CloudWatch, etc.)
  • Panel — a single visualization (graph, gauge, table, stat)
  • Row — a group of panels with a shared theme (e.g. "Network")
  • Variables — dashboard-level placeholders (e.g. $host) that let you filter panels without editing them

A dashboard is only as good as its defaults. When you open it, the first 10 seconds should answer: Is anything wrong right now? Green/red status panels on top, trends below, and a time series selector that actually works.

How it works step by step

Building a Grafana dashboard for metrics follows a repeatable flow — from connecting data to publishing a shareable link.

  1. Install Grafana and start the service. - Use your distro's package manager (e.g. apt install grafana on Debian/Ubuntu, dnf on RHEL). - Start and enable the service with systemctl enable --now grafana-server.

  2. Access the web UI and log in. - Default URL: http://localhost:3000 - Default credentials: admin / admin (you'll be forced to change it on first login).

  3. Add a data source. - Navigate to Configuration → Data Sources → Add data source. - Choose Prometheus (or your stack's source) and set the URL (e.g. http://localhost:9090). - Click Save & Test — Grafana verifies connectivity and shows a green "Data source is working" message.

  4. Create a dashboard. - Dashboards → New → New Dashboard → Add a new panel. - In the query editor, pick your data source and write a PromQL query, e.g. rate(node_cpu_seconds_total{mode="idle"}[5m]) to show idle CPU. - Configure the visualization type, title, and unit; adjust the time range to last 15 minutes for a sensible default.

  5. Add more panels for each metric group — CPU, memory, disk, network.

  6. Set up variables so the dashboard becomes reusable across hosts and environments.

  7. Save, share, and iterate — export JSON or build a provisioning file if you want version-controllable dashboards.

Hands-on walkthrough

Let's build a functional dashboard for a single Linux host. We'll assume Prometheus is already scraping node_exporter (if not, refer to the previous lesson on setting up exporters).

Step 1: Install and run Grafana

# On Debian/Ubuntu
sudo apt update && sudo apt install -y grafana
sudo systemctl enable --now grafana-server

# Verify
systemctl status grafana-server --no-pager

Step 2: Log in and add Prometheus

Open http://localhost:3000, log in with admin/admin, then set a strong password. Go to Configuration → Data Sources → Add data source, pick Prometheus, and set the URL to http://localhost:9090. Click Save & Test — you should see the green success banner.

Step 3: Create your first panel — CPU usage

From Dashboards → New → Add panel:

Query editor:
- Data source: Prometheus
- Query: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
- Legend: {{instance}}
- Unit: percent (0-100)
- Visualisation: Time series

This shows the non-idle CPU percentage — a more intuitive "busy" metric. Add a threshold (e.g. red above 85) by clicking on Thresholds in the panel edit.

Step 4: Add memory, disk, and network panels

Memory used:
- Query: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100
- Unit: percent

Disk space used:
- Query: (1 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})) * 100
- Unit: percent
- Tip: filter to mountpoint="/" to avoid tons of per-disk series

Network receive bytes:
- Query: rate(node_network_receive_bytes_total[5m])
- Unit: B/s (or bits/s — pick and be consistent!)

Arrange panels into a sensible layout: status gauges on top, time series below.

Step 5: Add a host variable

Now make the dashboard reusable for multiple hosts.

  1. Dashboard settings → Variables → Add variable
  2. Name: host
  3. Type: Query
  4. Data source: Prometheus
  5. Query: label_values(node_uname_info, instance)
  6. Enable Multi-value and Include All option
  7. Update each panel's query to filter by instance=~"$host"
Query example after variable:
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle", instance=~"$host"}[5m])) * 100)

Now use the dropdown at the top of the dashboard to switch between hosts — without touching a single panel.

Step 6: Time range & refresh

Set the default time range to last 15 minutes and auto-refresh to 30s (dashboards settings → General). This makes the dashboard ready the moment you open it.

Expected output

When you save and open the dashboard, you'll see: - Four (or more) panels with live charts - A host dropdown filtering everything - Threshold colors (e.g. red CPU when above 85%) - A clean, shareable URL like http://localhost:3000/d/<uid>/my-host-dashboard

Compare options / when to choose what

Grafana supports many data sources, and your choice affects both dashboard design and query syntax. Here's a quick comparison:

Data source Best for Query language Notes
Prometheus Pull-based metrics, Kubernetes, cloud-native PromQL Most common with Grafana; great with node_exporter
InfluxDB Push-based, IoT, older stacks Flux or InfluxQL Good for high-cardinality event data
CloudWatch AWS services (EC2, RDS, Lambda) CloudWatch Metrics math Native AWS metrics, but lag and cost can be issues
Loki Logs, not metrics LogQL Use for log correlation, not usually for host metrics

For a Linux networking telemetry stack, Prometheus is the go-to — mature, well-documented, and designed for this exact use case. If you're already in AWS and only need EC2 metrics, CloudWatch might be simpler — no extra service to run. InfluxDB shines for high-write-rate IoT data.

Troubleshooting & edge cases

Panel shows "No data" - Check the data source is reachable from the Grafana server: curl http://localhost:9090/api/v1/targets from the Grafana host. - Verify your query matches the metric name — common typo: node_cpu_seconds_total vs node_cpu. - Look for time range issues: if you set last 1 minute, node_exporter only scrapes every 15s — you may need at least 2-3 minutes of data.

Missing host variables - label_values only works if the label instance exists on the metric. Run curl 'http://localhost:9090/api/v1/query?query=node_uname_info' to verify. If no results, your exporter isn't running. - Ensure the variable name in the query is wrapped with ~ and " — exact match won't work with multi-value.

Login page loops or says "invalid credentials" - Check trunk access: default credentials are admin/admin — after first login you must change it. If locked out, reset with grafana-cli admin reset-admin-password newpass. - If you're behind a reverse proxy, set root_url in /etc/grafana/grafana.ini to match your public URL.

Dashboard loads slowly - Too many panels with heavy queries. Reduce the time range, add rate and avg to cut cardinality, or use recording rules for expensive PromQL queries. - Consider enabling caching (Grafana's caching plugin) or using a dedicated read replica if using a SQL-based source.

Wrong units or values - Double-check units: node_memory_MemTotal_bytes is bytes, not megabytes. Use Grafana's unit dropdown (bytes → GB) instead of manual division when possible. - For network rates, remember rate gives per-second — a 5m rate of bytes is the right approach; don't sum without rate.

What you learned & what's next

You now know how to build a Grafana dashboard for metrics from scratch — from connecting Prometheus to designing panels that actually answer questions. You've mastered the core loop: query, visualize, filter, iterate. You can explain the difference between data sources, you've countered common pitfalls like no-data panels and misconfigured variables, and you've made your dashboard reusable with variables.

This lesson covers the visualization side of telemetry. Next in the track, we'll move to alerting — turning these dashboards into proactive alarms (e.g. page on CPU > 90% for 10 minutes). Alerting is where monitoring stops being passive and starts saving your sleep.

Keep this dashboard as your foundation — you'll build alert rules on top of the same queries.

Practice recap

Build a two-panel dashboard for memory used and disk I/O on your local host using only PromQL queries you've learned. Add a $host variable that filters both panels, then set a threshold red at 90%. If you get stuck, revisit the troubleshooting section — then move on to the next lesson on alerting.

Common mistakes

  • Creating panels from raw counters without using rate(), leading to always-increasing graphs that are impossible to read.
  • Forgetting to filter on instance=~"$host" after adding a variable — so the dropdown does nothing and panels show all hosts mixed.
  • Setting units inconsistent between panels (e.g. bytes vs bits) — the chart is correct but the legend is misleading.
  • Using a too-short default time range (like last 1 minute) when scrapes every 15s — results in empty or sparse panels on first load.
  • Posting sensitive dashboards to public Grafana instances without changing default admin password.

Variations

  1. Provisioning dashboards as JSON in a Git repo and loading them via Grafana provisioning config — enables code review and CI/CD.
  2. Using the Grafana CLI or API to create dashboards programmatically instead of clicking through the UI.
  3. Building panels from a SQL data source (e.g. PostgreSQL) instead of Prometheus — different query syntax but same visualization principles.

Real-world use cases

  • A SRE team monitors a microservices cluster: CPU, memory, network, and disk panels per host, filtered by Kubernetes node.
  • A network admin tracks bandwidth and packet loss across multiple routers using SNMP exporters and a Grafana dashboard with a $router variable.
  • A startup uses Grafana to visualize customer-facing API latency and error rates from a Prometheus + Node.js exporter, triggering alerts via Alertmanager.

Key takeaways

  • A Grafana dashboard is a control room, not a data dump — every panel should answer a question.
  • Start with broad health checks on top, drill down into subsystems below.
  • Use variables to make a dashboard reusable across hosts and environments.
  • Match the data source to the use case: Prometheus for cloud-native, CloudWatch for AWS, InfluxDB for high-write IoT.
  • Always use rate() for counters and consistent units to keep graphs meaningful.
  • Version-control your dashboard JSON for collaboration and reproducibility.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.