Debug an empty Grafana panel
When to use
Section titled “When to use”A provisioned Grafana panel on https://veta.mnetcs.com/grafana/ shows "No data" or a partial render and you need to know why.
Inputs needed
Section titled “Inputs needed”- SSH to the server (
ssh <user>@<server-host>) - Browser open to the Grafana URL with the panel in question
- Open the panel in Grafana → Edit and inspect the query. Note the metric/log name and every label selector.
- Verify the source exists:
- Prometheus metric:
curl -sf http://<server-host>:9090/api/v1/series?match[]=<metric_name>— empty array means no series. - Loki stream:
curl -G --data-urlencode 'query={<labels>}' http://<server-host>:3100/loki/api/v1/query | jq—result: []means no log lines match those labels.
- Prometheus metric:
- Check the label conventions:
- Backend services emit metrics via OTel auto-instrumentation, which produces
job=<service-name>andservice=<service-name>labels via the OTel-collectorprometheus.remote_writeblock. Prometheus queries should usejob=orservice=. - Logs flow Loki via Alloy which adds
service_name=<container-name>. Loki queries should useservice_name=. - Getting it wrong on either side is the #1 cause of empty panels.
- Backend services emit metrics via OTel auto-instrumentation, which produces
- Verify the scrape works:
curl http://<server-host>:9090/api/v1/targets— every target should showhealth=up.- For Loki:
docker exec -it lgtm-alloy alloy-cli statsor look at alloy's/-/healthyendpoint.
- Check the time-range vs cardinality: a panel using
[30s]window on a sparse metric will hit zero windows on a quiet system. Widen to[5m]and see if data appears. - Service-down sanity check: if multiple panels are empty, the underlying service may be down.
ssh <user>@<server-host> 'supervisorctl status'— but on docker-compose deployments,docker compose psis the equivalent.
Verification
Section titled “Verification”After applying a fix:
- Reload the Grafana panel; the data should appear within the scrape interval (15s default).
- Confirm any other panels using the same source also work.
- If you changed a provisioned dashboard, restart Grafana:
docker compose up -d lgtm-grafana.
Common pitfalls
Section titled “Common pitfalls”- Editing the live dashboard via the UI — provisioned dashboards on the server are read-only at the file system level. Edits persist for the session but vanish on restart. Always edit the JSON in
observability/grafana/provisioning/dashboards/json/and commit. - Time-range too tight —
[30s]over a low-throughput service produces zero windows.[5m]is the usual minimum forrate()queries. - Disk full or Loki retention — if disk is full, Loki silently stops ingesting (no error in Grafana).
df -hon the server. - Forgetting
category=securityrouting — Grafana AlertManager routes by label. An alert without the expectedcategory=securitylabel falls through to the default channel.