Capstone — Full Monitoring Dashboard for Campus Library
Time for the real thing. This challenge chains everything you learned into one complete monitoring dashboard. Plan for about one hour.
Goal
By the end, you should have a Grafana dashboard with CPU, memory, request rate, and error panels — with variables, thresholds, and alert notifications.
Step 1 · The Stack
docker-compose.yml
services:
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
- ./provisioning:/etc/grafana/provisioning
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
node-exporter:
image: prom/node-exporter:latest
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--path.rootfs=/rootfs'
app:
image: nginx:alpine
ports:
- "8080:80"
volumes:
grafana-data:
Step 2 · Prometheus Config
prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'app'
static_configs:
- targets: ['app:80']
Step 3 · Auto-Provision Data Source
provisioning/datasources/prometheus.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
access: proxy
isDefault: true
Step 4 · Start and Build
Start everything
docker compose up -d
Open http://localhost:3000 → Create a new dashboard with these panels:
Row 1: Overview (Stat panels)
| Panel | Query | Type |
|---|---|---|
| CPU Usage | 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) | Gauge |
| Memory Usage | (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 | Gauge |
| Active Targets | count(up == 1) | Stat |
Row 2: Traffic (Time series)
| Panel | Query |
|---|---|
| Request Rate | sum(rate(http_requests_total[5m])) by (job) |
| Network Receive | rate(node_network_receive_bytes_total[device!="lo"][5m]) |
Row 3: Saturation (Time series)
| Panel | Query |
|---|---|
| Memory Over Time | (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 |
| Disk Usage | (1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 |
Step 5 · Add Variables
- Dashboard Settings → Variables → Add variable
- Name:
job, Query:label_values(up, job) - Add to panel queries:
rate(http_requests_total{job="$job"}[5m])
Step 6 · Add Alerts
- Edit the CPU Usage panel → Alert tab → Create alert rule
- Condition: CPU > 80% for 5 minutes
- Notification: Send to Slack or email
Step 7 · Clean Up
Stop everything
docker compose down -v
rm -f docker-compose.yml prometheus.yml
rm -rf provisioning/
Remember
This capstone chained: data source → panels → queries → variables → thresholds → alerts. This is exactly how production dashboards are built.