Describe the bug
By default the exporter builds a brand-new mongo.Client for every scrape and disconnects it when the scrape finishes. Each Prometheus scrape therefore pays for a full TCP connect, TLS handshake (when enabled), SCRAM authentication, and server/topology discovery against the monitored instance.
--mongodb.global-conn-pool exists to avoid this, but it is opt-in: at main.go:47 the flag carries no default: tag, so it defaults to false. (Compare --mongodb.direct-connect on the following line, which does declare default:"true".)
Where
exporter/exporter.go:296 — the non-pooled branch of getClient, comment and all:
// !e.opts.GlobalConnPool: create new client for every scrape.
client, err := connect(ctx, e.opts)
exporter/exporter.go:423 — connect() performs mongo.Connect followed by client.Ping.
exporter/exporter.go:341 — the deferred client.Disconnect(ctx) that tears it back down at the end of the scrape.
exporter/server.go:134 — /scrapeall repeats the same connect/disconnect cycle per exporter.
Why it matters
SCRAM is intentionally expensive: the server runs the configured iteration count on every authentication. At a 15s scrape interval that is roughly 5,760 full authentication handshakes per target per day, and the CPU cost lands on the monitored mongod, not on the exporter. Add TLS handshakes and repeated topology discovery on top. Connection churn also inflates mongod connection counters and can trip connection-rate alerting.
Expected behavior
Steady-state scraping should reuse a connection. Open questions for whoever picks this up:
- Should
--mongodb.global-conn-pool default to true? That is a behavior change for existing deployments and needs a deliberate call plus a release note, but reconnect-per-scrape is a surprising default for a Prometheus exporter.
- If the default stays
false, the flag at minimum deserves a prominent mention in README.md — today its cost is invisible to operators.
- The pooled path may need hardening first. In
getClient (exporter/exporter.go:278), when the cached client's Ping fails the function returns an error but leaves e.client populated and never rebuilds it. The Go driver recovers from transient topology failures on its own, so this self-heals in the common case, but it is worth confirming there is no state (rotated credentials, for example) where the exporter stays wedged until restart. That question should be settled before the pooled path becomes the default.
Related
Environment
Not environment-specific; applies to all builds from main (verified @ 9585218).
Describe the bug
By default the exporter builds a brand-new
mongo.Clientfor every scrape and disconnects it when the scrape finishes. Each Prometheus scrape therefore pays for a full TCP connect, TLS handshake (when enabled), SCRAM authentication, and server/topology discovery against the monitored instance.--mongodb.global-conn-poolexists to avoid this, but it is opt-in: atmain.go:47the flag carries nodefault:tag, so it defaults tofalse. (Compare--mongodb.direct-connecton the following line, which does declaredefault:"true".)Where
exporter/exporter.go:296— the non-pooled branch ofgetClient, comment and all:exporter/exporter.go:423—connect()performsmongo.Connectfollowed byclient.Ping.exporter/exporter.go:341— the deferredclient.Disconnect(ctx)that tears it back down at the end of the scrape.exporter/server.go:134—/scrapeallrepeats the same connect/disconnect cycle per exporter.Why it matters
SCRAM is intentionally expensive: the server runs the configured iteration count on every authentication. At a 15s scrape interval that is roughly 5,760 full authentication handshakes per target per day, and the CPU cost lands on the monitored
mongod, not on the exporter. Add TLS handshakes and repeated topology discovery on top. Connection churn also inflatesmongodconnection counters and can trip connection-rate alerting.Expected behavior
Steady-state scraping should reuse a connection. Open questions for whoever picks this up:
--mongodb.global-conn-pooldefault totrue? That is a behavior change for existing deployments and needs a deliberate call plus a release note, but reconnect-per-scrape is a surprising default for a Prometheus exporter.false, the flag at minimum deserves a prominent mention inREADME.md— today its cost is invisible to operators.getClient(exporter/exporter.go:278), when the cached client'sPingfails the function returns an error but leavese.clientpopulated and never rebuilds it. The Go driver recovers from transient topology failures on its own, so this self-heals in the common case, but it is worth confirming there is no state (rotated credentials, for example) where the exporter stays wedged until restart. That question should be settled before the pooled path becomes the default.Related
appname=sdkwithout using the connection pool.canceled while checking out a connection from connection poolduring$dbstats./probetargets. Its per-target handler cache is what makes--mongodb.global-conn-poolreachable for dynamically supplied targets at all (e.clientis per-Exporterstate), so the two interact. Note that cache is currently unbounded, which matters more once pooling is on.Environment
Not environment-specific; applies to all builds from
main(verified @ 9585218).