fix(prometheus): keep looking for a Prometheus the agent could not find at boot - #601
fix(prometheus): keep looking for a Prometheus the agent could not find at boot#601mayankpande88 wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces dynamic Prometheus discovery after startup, allowing the agent to register Prometheus actions unconditionally and update the client's URL in the background once a Prometheus service is discovered. Feedback on these changes points out that other components initialized at startup, such as the Telemetry Poster and Grafana Proxy, still rely on the static configuration URL and will not receive the dynamically discovered URL, which could lead to incomplete telemetry and failing proxied queries.
|
Good catch on both — that was a real gap I introduced, since the boot-time path used to write the discovered URL back into Fixed in 57a779f:
I checked the other two |
|
📦 Image Tags Updated |
…nd at boot
Service discovery ran exactly once, during startup, and the result decided
for the life of the process whether prometheus_* actions, the enrichers,
rightsizing and the service map were registered at all. An agent that came
up before its Prometheus — a fresh cluster where both are installed
together, or a cluster where monitoring is added later — therefore stayed
blind to it until someone restarted the pod. The only trace was one warning
in the boot log, so from the outside it looked like the product simply had
no metrics: "no data" on charts, and no right-sizing recommendations on
workloads that obviously needed them.
Discovery is no longer a decision made once:
- The Prometheus client is always constructed, with or without a URL, so
its actions are always registered. Calls made before a URL is known fail
with "prometheus: base URL not configured" instead of "unknown action".
- Its base URL is settable at runtime (guarded by an RWMutex; every request
reads it fresh), so a URL found later needs no re-registration.
- When no URL is configured at boot, a watcher re-runs discovery every 5
minutes and points the client at the first Prometheus that appears. It
builds a fresh Discoverer per attempt: FindFirst caches misses for an
hour, which would otherwise freeze the retry after the first one.
Service-map, alert-rules and continuous_rightsizing lose their promClient
!= nil gates accordingly; each already reports the missing URL itself. The
health badge is unaffected — prometheusConnected still probes the live URL,
so it stays false until one is found.
…d telemetry Both read cfg.PrometheusURL, which the watcher does not touch — it cannot, without racing the goroutines that read cfg. So on a late discovery the /prometheus-v2/* proxy route kept 503-ing and telemetry kept reporting an empty Prometheus URL alongside a connected badge. Telemetry now reports promClient.URL(), evaluated per tick. The proxy gains an optional PrometheusURLFn consulted per request, which main wires to promClient.URL; the static field stays for every other caller.
57a779f to
7b9dea8
Compare
Summary
Prometheus service discovery ran once, at startup, and that one result decided for the life of the process whether
prometheus_*actions, the enrichers, right-sizing and the service map were registered at all.So an agent that started before its Prometheus stayed blind to it until someone restarted the pod. That happens more easily than it sounds: a fresh cluster where the agent and kube-prometheus-stack are installed together (the Service does not exist yet when we look), or any cluster where monitoring is added afterwards. The only trace was a single
WARNin the boot log — from the outside it just looked like the product had no metrics: empty charts, and no right-sizing recommendations on workloads that plainly needed them.Discovery is no longer a one-shot decision:
prometheus: base URL not configuredrather thanunknown action.service_map,alert_rulesandcontinuous_rightsizinglose theirpromClient != nilgates accordingly — each already reports the missing URL itself.The install script is unaffected: it still passes
--set globalConfig.prometheus_url=..., and an explicitly configured URL short-circuits all of this.Type of change
Chart version
Test plan
make validatepasses inrunner/; full suite green under-race;golangci-lint runclean on the changed files (the one repo-widegosecG704 inpkg/observability/signoz/client.gois pre-existing and untouched).Tests added:
TestWatchUntilFound_PicksUpAServiceAddedLater— nothing to find, then a Prometheus Service appears; the watcher reports it.TestWatchUntilFound_DoesNotInheritTheNegativeCache— guards the subtle part. Verified by regression: rewriting the watcher to reuse oneDiscoverermakes it fail, becauseFindFirstcaches misses for an hour and would freeze the retry after the first attempt for the rest of the process's life.TestSetURL_MakesAnUnconfiguredClientWork— a client built with no URL rejects queries, then serves them afterSetURL, with the trailing slash trimmed.TestSetURL_IsSafeWhileQueriesRun— concurrentSetURLandQueryunder-race, since the watcher writes the URL from its own goroutine while handlers read it.How to verify on a cluster
globalConfig.prometheus_url. The runner logsprometheus not configured: ... retry_interval=5m0sand the account's Prometheus health badge reads disconnected.prometheus: base URL not configuredrather than failing as an unknown action.helm installkube-prometheus-stack into that cluster and wait up to 5 minutes.prometheus discovered after startup ... url=http://...:9090with no pod restart, the health badge flips to connected, metrics queries answer, and right-sizing recommendations start appearing on the next scan.Related issues
None open for this. Found while verifying a customer evaluation report of "metrics unavailable" against the code.