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:

VraagDashboard
“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:

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

Op het cluster overzicht, link naar namespace-specifieke views:

URL: /d/namespace-view?var-namespace=${namespace}
Title: Drill down naar namespace

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:

  1. Home — Alles OK? (één blik)
  2. SLOs — Haal ik mijn objectives?
  3. Cluster — Kubernetes health
  4. Service Debug — Variabele-gedreven deep dive
  5. 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

  1. Dashboard niet geopend in 30 dagen → verplaats naar Archief folder
  2. 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.