You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two follow-ups from #9773, both about the watchable_* control-plane metrics being hard to read. They are independent and can be done separately.
1. watchable_depth is always 0, and the dashboard graphs it
watchable_depth is recorded as len(snapshots) (internal/message/watchutil.go:135), where snapshots is the channel returned by watchable.Map.Subscribe(). That channel is unbuffered — downstream := make(chan Snapshot[K, V]) in the watchable library — so the gauge can only ever be 0.
This is not just dead weight. The shipped Grafana dashboard graphs it, so operators see a flat zero and can reasonably read it as "no backlog" while the control plane is in fact seconds behind. That misreading happened during a real incident investigation.
Removing the metric is not straightforward, because the dashboard also uses it as a template variable source, so the $Runner and $Namespace dropdowns would break and take every filtered panel with them:
Repoint the depth panel at something meaningful. watchable_debounce_pending (added in performance: add opt-in debounce for resource updates #9773) reports how many updates were merged per flush, but only when debouncing is enabled, so a panel that works in both modes may need a different signal.
Move the two label_values queries onto a metric that is always present with the same runner/namespace labels — watchable_subscribe_total would do.
Only then decide whether to deprecate and remove the gauge, or redefine what it measures. Either is a breaking change for anyone with their own dashboards or alerts, so it wants a deprecation note.
2. watchable_subscribe_duration_seconds has poor resolution below 10s
The buckets are {0.001, 0.01, 0.1, 1, 5, 10, 30, 60, 120} (internal/message/metrics.go:31). #9773 appended 30, 60, 120 so the tail is no longer hidden, but deliberately did not touch the existing boundaries, since removing them is breaking.
The gaps that remain are 0.1 → 1 (10x) and 1 → 5 (5x). A control plane whose translations take ~2s puts every observation in (1, 5], and because histogram_quantile interpolates within a bucket, p50/p95/p99 all come back somewhere in 1–5s with no discriminating power — the same numbers whether things are healthy or steadily degrading, until they cross 5s. A sub-second control plane has the same problem in (0.1, 1].
This repo already has better-spaced buckets for the same kind of measurement, from the k8s rest client (internal/metrics/restclient/metrics.go:24):
Adopting that spacing, extended to 120s, would give roughly 2–2.5x steps throughout. It removes the 0.001, 1 and 5 boundaries, so anything referencing those le values breaks — hence a separate change with a breaking-change note.
Two follow-ups from #9773, both about the
watchable_*control-plane metrics being hard to read. They are independent and can be done separately.watchable_depthis always 0, and the dashboard graphs itwatchable_depthis recorded aslen(snapshots)(internal/message/watchutil.go:135), wheresnapshotsis the channel returned bywatchable.Map.Subscribe(). That channel is unbuffered —downstream := make(chan Snapshot[K, V])in the watchable library — so the gauge can only ever be 0.This is not just dead weight. The shipped Grafana dashboard graphs it, so operators see a flat zero and can reasonably read it as "no backlog" while the control plane is in fact seconds behind. That misreading happened during a real incident investigation.
Removing the metric is not straightforward, because the dashboard also uses it as a template variable source, so the
$Runnerand$Namespacedropdowns would break and take every filtered panel with them:Suggested order of work:
Repoint the depth panel at something meaningful.
watchable_debounce_pending(added in performance: add opt-in debounce for resource updates #9773) reports how many updates were merged per flush, but only when debouncing is enabled, so a panel that works in both modes may need a different signal.Move the two
label_valuesqueries onto a metric that is always present with the samerunner/namespacelabels —watchable_subscribe_totalwould do.Only then decide whether to deprecate and remove the gauge, or redefine what it measures. Either is a breaking change for anyone with their own dashboards or alerts, so it wants a deprecation note.
2.
watchable_subscribe_duration_secondshas poor resolution below 10sThe buckets are
{0.001, 0.01, 0.1, 1, 5, 10, 30, 60, 120}(internal/message/metrics.go:31). #9773 appended30, 60, 120so the tail is no longer hidden, but deliberately did not touch the existing boundaries, since removing them is breaking.The gaps that remain are
0.1 → 1(10x) and1 → 5(5x). A control plane whose translations take ~2s puts every observation in(1, 5], and becausehistogram_quantileinterpolates within a bucket, p50/p95/p99 all come back somewhere in 1–5s with no discriminating power — the same numbers whether things are healthy or steadily degrading, until they cross 5s. A sub-second control plane has the same problem in(0.1, 1].This repo already has better-spaced buckets for the same kind of measurement, from the k8s rest client (
internal/metrics/restclient/metrics.go:24):Adopting that spacing, extended to 120s, would give roughly 2–2.5x steps throughout. It removes the
0.001,1and5boundaries, so anything referencing thoselevalues breaks — hence a separate change with a breaking-change note.