Skip to content

Commit f774e70

Browse files
impimpademidoffidoqo
authored
PMM-14141: Respect Prometheus scrape-timeout header (#1107)
* Fix parsing of X-Prometheus-Scrape-Timeout-Seconds header The previous implementation expected this header to be an integer, but vmagent may send it as a float. This caused incorrect handling in `mongodb_exporter`. Updated to support float values. * Avoid stale connections by pinging on acquire The exporter was returning cached MongoDB connections without validating their health. This meant that if a connection had become unhealthy, subsequent operations would fail after a delay (serverSelectionTimeout etc), causing the entire request to be slower than it should be. This commit adds `Ping` check before returning a cached client. * Update exporter/exporter.go Co-authored-by: Alex Demidoff <alexander.demidoff@percona.com> --------- Co-authored-by: Alex Demidoff <alexander.demidoff@percona.com> Co-authored-by: Michael Okoko <10512379+idoqo@users.noreply.github.com>
1 parent 06b081a commit f774e70

File tree

1 file changed

+18
-8
lines changed

1 file changed

+18
-8
lines changed

exporter/exporter.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,13 @@ func (e *Exporter) getClient(ctx context.Context) (*mongo.Client, error) {
273273
e.clientMu.Lock()
274274
defer e.clientMu.Unlock()
275275

276-
// If client is already initialized, return it.
276+
// If client is already initialized, and Ping is successful -- return it.
277277
if e.client != nil {
278+
err := e.client.Ping(ctx, nil)
279+
if err != nil {
280+
return nil, fmt.Errorf("cannot connect to MongoDB: %w", err)
281+
}
282+
278283
return e.client, nil
279284
}
280285

@@ -300,20 +305,25 @@ func (e *Exporter) getClient(ctx context.Context) (*mongo.Client, error) {
300305
// run for hooking up custom HTTP servers.
301306
func (e *Exporter) Handler() http.Handler {
302307
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
303-
seconds, err := strconv.Atoi(r.Header.Get("X-Prometheus-Scrape-Timeout-Seconds"))
304-
// To support older ones vmagents.
305-
if err != nil {
306-
seconds = 10
308+
scrapeTimeoutHeader := r.Header.Get("X-Prometheus-Scrape-Timeout-Seconds")
309+
seconds := 10.0
310+
311+
if scrapeTimeoutHeader != "" {
312+
if parsedSeconds, err := strconv.ParseFloat(scrapeTimeoutHeader, 64); err == nil {
313+
seconds = parsedSeconds
314+
} else {
315+
e.logger.Info("Invalid X-Prometheus-Scrape-Timeout-Seconds header", "error", err)
316+
}
307317
}
308-
seconds -= e.opts.TimeoutOffset
318+
seconds -= float64(e.opts.TimeoutOffset)
309319

310320
var client *mongo.Client
311-
ctx, cancel := context.WithTimeout(r.Context(), time.Duration(seconds)*time.Second)
321+
ctx, cancel := context.WithTimeout(r.Context(), time.Duration(seconds*float64(time.Second)))
312322
defer cancel()
313323

314324
requestOpts := GetRequestOpts(r.URL.Query()["collect[]"], e.opts)
315325

316-
client, err = e.getClient(ctx)
326+
client, err := e.getClient(ctx)
317327
if err != nil {
318328
e.logger.Error("Cannot connect to MongoDB", "error", err)
319329
}

0 commit comments

Comments
 (0)