Je hebt Grafana. Je hebt Prometheus metrics. Je hebt logs in Loki en traces in Tempo.
Je hebt ook 47 dashboards waar niemand naar kijkt.
Dashboard rot is echt. Teams maken dashboards voor elke mogelijke metric, elke service, elk potentieel probleem. Zes maanden later weet niemand meer wat de helft ervan toont of waarom ze bestaan.
Goede dashboards zijn anders. Ze worden dagelijks geopend. Ze beantwoorden vragen voor je ze stelt. Ze helpen je je systeem te begrijpen, niet alleen nummers te tonen.
Waarom Dashboards Falen
Te Veel Panels
Het dashboard heeft 30 panels. Elk toont een andere metric. Samen tonen ze niets — omdat niemand 30 grafieken tegelijk kan verwerken.
Verkeerd Abstractieniveau
Het dashboard toont CPU, memory en disk voor elke pod. Nuttig voor debuggen, nutteloos voor begrijpen of dingen werken.
Geen Context
Nummers zonder context zijn betekenisloos. “500 requests/seconde” — is dat goed? Slecht? Normaal?
Gebouwd en Vergeten
Gemaakt tijdens een incident, nooit bijgewerkt. Toont nu metrics voor services die twee jaar geleden hernoemd zijn.
Dashboard Design Principes
1. Eén Doel Per Dashboard
Elk dashboard beantwoordt één vraag:
| Vraag | Dashboard |
|---|---|
| “Is het systeem gezond?” | Service overzicht |
| “Waarom is deze service traag?” | Service deep dive |
| “Wat gebeurde er om 3 uur ’s nachts?” | Incident onderzoek |
| “Halen we onze SLOs?” | SLO dashboard |
Mix geen doelen. Een health-check dashboard moet geen debugging panels hebben.
2. Progressieve Onthulling
Begin met het antwoord, drill down voor details:
Level 1: Is alles OK? (groen/geel/rood)
↓
Level 2: Welke service heeft problemen?
↓
Level 3: Welke specifieke metric is fout?
↓
Level 4: Ruwe data voor debugging
Elk level is een ander dashboard of sectie, aan elkaar gelinkt.
3. Context Boven Nummers
Ruwe nummers zijn nutteloos. Voeg toe:
- Thresholds: Kleur verandert wanneer metrics SLO grenzen kruisen
- Vergelijkingen: Vandaag vs vorige week, deze deploy vs vorige
- Annotaties: Deployments, incidenten, config changes gemarkeerd op grafieken
4. Ontwerp voor Scannen
Als je het dashboard niet in 5 seconden kunt begrijpen, is het te complex.
Gebruik:
- Stat panels voor huidige staat (grote nummers, kleurgecodeerd)
- Time series voor trends (wanneer begon dit?)
- Heatmaps voor distributies (latency percentielen)
Vermijd:
- Tabellen met 50 rijen
- Grafieken met 20 overlappende lijnen
- Pie charts (vermijd altijd pie charts)
Essentiële Dashboard Types
Service Overzicht Dashboard
Het “is alles OK?” dashboard. Eén per service of servicegroep.
# Panels (boven naar onder, links naar rechts)
Rij 1: Status (stat panels)
- Beschikbaarheid (% uptime laatste 24u)
- Error Rate (huidig, kleurgecodeerd)
- P99 Latency (huidig, kleurgecodeerd)
- Actieve Instances (aantal)
Rij 2: Trends (time series)
- Request Rate (gestapeld per status code)
- Latency (P50, P95, P99 lijnen)
- Error Rate (percentage over tijd)
Rij 3: Resources (gauges)
- CPU Gebruik (% van limit)
- Memory Gebruik (% van limit)
- Pod Count (huidig vs gewenst)
Belangrijke queries:
# Beschikbaarheid (percentage succesvolle requests)
sum(rate(http_requests_total{status!~"5.."}[5m])) /
sum(rate(http_requests_total[5m])) * 100
# Error rate
sum(rate(http_requests_total{status=~"5.."}[5m])) /
sum(rate(http_requests_total[5m])) * 100
# P99 latency
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
)
SLO Dashboard
Volgt Service Level Objectives. Cruciaal voor betekenisvolle alerting.
Rij 1: SLO Status (stat panels)
- Beschikbaarheid SLO (99.9% target)
- Latency SLO (P99 < 500ms target)
- Error Budget Resterend (%)
Rij 2: Burn Rate (time series)
- Error budget consumptie snelheid
- Voorspelde budget uitputting
Rij 3: SLI Breakdown (time series)
- Beschikbaarheid over tijd
- Latency percentielen over tijd
Error budget berekening:
# Error budget resterend (voor 99.9% SLO over 30 dagen)
1 - (
(1 - (sum(rate(http_requests_total{status!~"5.."}[30d])) /
sum(rate(http_requests_total[30d])))) /
0.001 # 0.1% error budget
)
Kubernetes Cluster Dashboard
Overzicht van cluster health. Geen per-pod details — dat is voor debugging.
Rij 1: Cluster Status
- Nodes Ready / Totaal
- Pods Running / Scheduled
- PVCs Bound / Totaal
Rij 2: Resource Gebruik
- CPU: Gebruikt / Requested / Allocatable
- Memory: Gebruikt / Requested / Allocatable
Rij 3: Workload Health
- Deployments Available / Totaal
- StatefulSets Ready / Totaal
- DaemonSets Ready / Totaal
Rij 4: Recente Events (tabel)
- Warning events van afgelopen uur
Debugging Dashboard
Voor incident onderzoek. Meer gedetailleerd, acceptabele complexiteit.
Rij 1: Service Selectie (variabelen)
- Namespace dropdown
- Service dropdown
- Pod dropdown
Rij 2: Request Flow
- Inkomende requests per endpoint
- Uitgaande requests per bestemming
- Error breakdown per type
Rij 3: Resource Details
- CPU per container (time series)
- Memory per container (time series)
- Network I/O (time series)
Rij 4: Logs Integratie
- Link naar Loki met pre-gefilterde query
- Recente error log count
Praktische Panel Voorbeelden
Request Rate met Status Codes
sum by (status_code) (
rate(http_requests_total{service="$service"}[5m])
)
Visualisatie instellingen:
- Stack series
- Kleur per status: 2xx groen, 3xx blauw, 4xx geel, 5xx rood
Latency Heatmap
sum(rate(http_request_duration_seconds_bucket{service="$service"}[5m])) by (le)
Visualisatie: Heatmap
- Toont latency distributie over tijd
- Hot spots onthullen latency spikes
Resource Gebruik vs Limits
# CPU gebruik percentage van limit
sum(rate(container_cpu_usage_seconds_total{pod=~"$pod"}[5m])) /
sum(kube_pod_container_resource_limits{resource="cpu", pod=~"$pod"}) * 100
Visualisatie: Gauge
- Thresholds: 0-70 groen, 70-90 geel, 90-100 rood
Pod Restart Indicator
sum(increase(kube_pod_container_status_restarts_total{namespace="$namespace"}[1h])) by (pod)
Visualisatie: Stat panel
- Toon alleen als > 0
- Links naar pod logs
Dashboard Variabelen
Variabelen maken dashboards herbruikbaar. Essentiële:
# Namespace variabele
name: namespace
query: label_values(kube_pod_info, namespace)
multi: true
include_all: true
# Service variabele (gefilterd op namespace)
name: service
query: label_values(kube_pod_info{namespace=~"$namespace"}, pod)
multi: false
# Tijd vergelijking
name: comparison
options:
- 1h geleden
- 1d geleden
- 1w geleden
Gebruik in queries:
# Huidige waarde
sum(rate(http_requests_total{namespace="$namespace"}[5m]))
# Vergelijkingswaarde (offset met geselecteerde tijd)
sum(rate(http_requests_total{namespace="$namespace"}[5m] offset $comparison))
Annotaties voor Context
Markeer belangrijke events op grafieken:
# Deployment annotaties
name: Deployments
datasource: Prometheus
query: changes(kube_deployment_status_observed_generation{deployment="$service"}[5m]) > 0
tags: deployment
# Alert annotaties
name: Alerts
datasource: Alertmanager
filter: service="$service"
tags: alert
Nu als latency piekt, zie je direct of het correleert met een deployment.
Dashboards Aan Elkaar Linken
Maak navigatie tussen dashboards:
Data Links
Op een service panel, link naar het service detail dashboard:
URL: /d/service-detail?var-service=${__field.labels.service}
Title: Bekijk ${__field.labels.service} details
Panel Links
Op het cluster overzicht, link naar namespace-specifieke views:
URL: /d/namespace-view?var-namespace=${namespace}
Title: Drill down naar namespace
Explore Links
Link naar Loki voor logs:
URL: /explore?left=["now-1h","now","Loki",{"expr":"{namespace=\"${namespace}\",pod=~\"${pod}\"}"}]
Title: Bekijk logs in Explore
Dashboard Organisatie
Folder Structuur
├── Overzicht
│ ├── Platform Health
│ └── SLO Samenvatting
├── Services
│ ├── API Gateway
│ ├── Auth Service
│ └── ...
├── Infrastructuur
│ ├── Kubernetes Cluster
│ ├── Nodes
│ └── Storage
├── Debugging
│ ├── Service Debug
│ └── Incident Onderzoek
└── Archief
└── (oude dashboards, verborgen)
Naamconventie
[Categorie] - [Onderwerp] - [Type]
Voorbeelden:
- Services - API Gateway - Overzicht
- Services - API Gateway - Debug
- Infrastructuur - Kubernetes - Nodes
- SLO - Platform - 30d
Starring en Home Dashboard
Stel het belangrijkste dashboard in als Grafana home. Star veelgebruikte dashboards.
Dashboard as Code
Sla dashboards op in Git. Deploy met ArgoCD.
Grafana Dashboard ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: service-overview-dashboard
labels:
grafana_dashboard: "1"
data:
service-overview.json: |
{
"title": "Service Overview",
"uid": "service-overview",
"panels": [
...
]
}
Grafonnet (Jsonnet library)
local grafana = import 'grafonnet/grafana.libsonnet';
local dashboard = grafana.dashboard;
local prometheus = grafana.prometheus;
dashboard.new(
'Service Overview',
uid='service-overview',
tags=['service', 'overview'],
)
.addPanel(
grafana.statPanel.new(
'Error Rate',
datasource='Prometheus',
).addTarget(
prometheus.target(
'sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100',
)
),
gridPos={ x: 0, y: 0, w: 6, h: 4 },
)
Mijn Dashboard Setup
Voor mijn homelab cluster onderhoud ik exact 5 dashboards:
- Home — Alles OK? (één blik)
- SLOs — Haal ik mijn objectives?
- Cluster — Kubernetes health
- Service Debug — Variabele-gedreven deep dive
- Incident — Volledige observability stack integratie
Dat is het. Ik weersta de verleiding om meer te maken.
Elk dashboard heeft een doel. Elk wordt wekelijks of vaker gebruikt. Als een dashboard een maand niet geopend wordt, verwijder ik het.
Dashboard Rot Voorkomen
Regelmatige Review
Maandelijks: Review alle dashboards
- Welke werden deze maand geopend?
- Zijn queries nog geldig?
- Kloppen thresholds nog met de huidige realiteit?
Sunset Proces
- Dashboard niet geopend in 30 dagen → verplaats naar Archief folder
- Dashboard 60 dagen in Archief → verwijder
Documentatie
Elk dashboard heeft een beschrijving:
Doel: Snelle health check voor productie services
Doelgroep: On-call engineers
Wanneer te gebruiken: Dagelijkse check, incident first response
Links naar: Service Debug dashboard voor details
Waarom Dit Ertoe Doet
Dashboards zijn communicatiemiddelen. Een goed dashboard vertelt een verhaal over je systeem. Een slecht dashboard is ruis die mensen traint om monitoring te negeren.
Je observability stack verzamelt enorme hoeveelheden data. Dashboards zijn hoe je die data nuttig maakt. Ontwerp ze met intentie, onderhoud ze met discipline, en verwijder ze wanneer ze hun plek niet meer verdienen.
Het beste dashboard is het dashboard waar naar gekeken wordt.
Metrics zijn makkelijk te verzamelen. Dashboards zijn makkelijk te maken. Begrip is moeilijk te bereiken. Ontwerp voor begrip.
