01 · Notice the gap
A service with a metrics port, and nothing scraping it.
Every day, the monitoring scan lists the workloads in the cluster.
It matches them to their Services and to every existing
ServiceMonitor and PodMonitor. These are Kubernetes
objects that tell Prometheus what to scrape. A ServiceMonitor
selects Services, not pods. So the scan follows the real chain:
monitor → Service → workload, and it respects namespace selectors.
orders-api has a port called metrics on
9102. No monitor reaches it. The scan skips workloads that someone
scaled to zero on purpose, so a parked relic never gets a monitor.
02 · Check the endpoint really serves
It asks the endpoint before it writes a line of YAML.
A port name is a hint, not proof. Before it proposes anything, the
assistant fetches /metrics with a read-only probe. It
checks that the endpoint answers in Prometheus exposition format.
The same response shows which metric families exist. Later, the
assistant builds the dashboard from these families.
03 · Propose the ServiceMonitor
Labels copied from the live Service, not guessed.
The generated ServiceMonitor selects the Service by its actual
labels and names the actual port. It also carries the release label.
Your Prometheus operator or Alloy instance uses that label to find
monitors.
Sometimes the Helm chart (a packaged application) already ships a
monitor behind a values flag. Then you get the values flip
instead of a hand-written manifest. The chart stays the owner.
04 · Merged. Data starts flowing.
Your collector does the scraping. The assistant reads the result.
After you merge, Flux applies the monitor. Your collector
(Prometheus, or Grafana Alloy) starts to scrape. The series arrive
in your metrics backend.
The assistant never writes to that pipeline. It only reads from the
backend, one tenant at a time, when it builds and checks the
dashboard.
05 · Find or write the dashboard
Community dashboards first. Generated only when none fit.
For well-known exporters (node, Redis, PostgreSQL, Traefik…), the
assistant prefers the maintained grafana.com dashboard. It
adapts the dashboard to your datasource and namespace variables.
orders-api is your own code, so there is nothing to
import. The assistant drafts a dashboard from the metric families it
saw: request rate, latency histogram (how long requests take),
errors, business counters and runtime.
06 · Prove every panel
Each query runs against your data before you see it.
The assistant runs every panel expression against the metrics
backend. It drops panels that return nothing and counts them. A
grounded panel is one that is proven to return data. If no panel is
grounded, the assistant does not ship the dashboard quietly. It
holds the dashboard for review and names the reason.
- The assistant catches
rate() over a gauge and escalates it.
- Every
$variable needs a declaration.
- Datasource and namespace are variables. They are never hard-coded.
07 · Ship it the GitOps way
A ConfigMap in git. Grafana's sidecar does the rest.
The assistant wraps the dashboard in a ConfigMap with the
grafana_dashboard label. It places the ConfigMap in the
tenant's folder. It also records on the ConfigMap how many queries
were grounded, and when.
You merge it, and Flux applies it. The Grafana sidecar picks it up.
There is no click-ops (manual work in the UI). No dashboard exists
only in one Grafana's database.
08 · The result
A dashboard that maps one-to-one onto what the service exposes.
Every panel shows one of the metric families the probe saw
in step 2. Nothing is invented. Nothing is empty.
The assistant audits committed dashboards for known defects and
repairs them by MR. A scheduled re-check of these dashboards is in
development. It will also find a panel that goes dark after a
service change.