From 156eabc11bc0fbcf16147516f3fa97bbf629a014 Mon Sep 17 00:00:00 2001 From: Sai Asish Y Date: Thu, 14 May 2026 22:47:30 -0700 Subject: [PATCH] exporter: rename scrapeall instance label --- README.md | 6 +++--- exporter/multi_target_test.go | 8 ++++---- exporter/server.go | 21 ++++++++++++++------- exporter/server_test.go | 30 ++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 exporter/server_test.go diff --git a/README.md b/README.md index 6b65778ec..dfa3c62f2 100644 --- a/README.md +++ b/README.md @@ -129,14 +129,14 @@ You can use the --split-cluster option to split all cluster nodes into separate #### Overall targets request endpoint -There is an overall targets endpoint **/scrapeall** that queries all the targets in one request. It can be used to store multiple node metrics without separate target requests. In this case, each node metric will have a **instance** label containing the node name as a host:port pair (or just host if no port was not specified). For example, for mongodb_exporter running with the options: +There is an overall targets endpoint **/scrapeall** that queries all the targets in one request. It can be used to store multiple node metrics without separate target requests. In this case, each node metric will have a **mongo_instance** label containing the node name as a host:port pair (or just host if no port was not specified). This avoids a collision with Prometheus's reserved `instance` label. For example, for mongodb_exporter running with the options: ``` --mongodb.uri="mongodb://host1:27015,host2:27016" --split-cluster=true ``` we get metrics like this: ``` -mongodb_up{instance="host1:27015"} 1 -mongodb_up{instance="host2:27016"} 1 +mongodb_up{mongo_instance="host1:27015"} 1 +mongodb_up{mongo_instance="host2:27016"} 1 ``` #### Enabling collstats metrics gathering diff --git a/exporter/multi_target_test.go b/exporter/multi_target_test.go index 8278591d9..291578c71 100644 --- a/exporter/multi_target_test.go +++ b/exporter/multi_target_test.go @@ -105,10 +105,10 @@ func TestOverallHandler(t *testing.T) { }, } expected := []*regexp.Regexp{ - regexp.MustCompile(`mongodb_up{[^\}]*instance="standalone"[^\}]*} 1\n`), - regexp.MustCompile(`mongodb_up{[^\}]*instance="s1"[^\}]*} 1\n`), - regexp.MustCompile(`mongodb_up{[^\}]*instance="s2"[^\}]*} 1\n`), - regexp.MustCompile(`mongodb_up{[^\}]*instance="s3"[^\}]*} 0\n`), + regexp.MustCompile(`mongodb_up{[^\}]*mongo_instance="standalone"[^\}]*} 1\n`), + regexp.MustCompile(`mongodb_up{[^\}]*mongo_instance="s1"[^\}]*} 1\n`), + regexp.MustCompile(`mongodb_up{[^\}]*mongo_instance="s2"[^\}]*} 1\n`), + regexp.MustCompile(`mongodb_up{[^\}]*mongo_instance="s3"[^\}]*} 0\n`), } exporters := make([]*Exporter, len(opts)) diff --git a/exporter/server.go b/exporter/server.go index e7c4f5cd4..f7d78f4fc 100644 --- a/exporter/server.go +++ b/exporter/server.go @@ -43,6 +43,10 @@ type ServerOpts struct { DisableDefaultRegistry bool } +// Label added by /scrapeall to identify the monitored MongoDB target. +// Use a non-Prometheus-reserved name so Prometheus does not rewrite it. +const scrapeAllInstanceLabel = "mongo_instance" + // RunWebServer runs the main web-server func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *slog.Logger) { mux := http.NewServeMux() @@ -104,7 +108,7 @@ func multiTargetHandler(serverMap ServerMap) http.HandlerFunc { } // OverallTargetsHandler is a handler to scrape all the targets in one request. -// Adds instance label to each metric. +// Adds a MongoDB-target label to each metric. func OverallTargetsHandler(exporters []*Exporter, logger *slog.Logger) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { seconds, err := strconv.Atoi(r.Header.Get("X-Prometheus-Scrape-Timeout-Seconds")) @@ -153,12 +157,7 @@ func OverallTargetsHandler(exporters []*Exporter, logger *slog.Logger) http.Hand registry.MustRegister(gc) } - hostlabels := prometheus.Labels{} - if e.opts.NodeName != "" { - hostlabels["instance"] = e.opts.NodeName - } - - gw := NewGathererWrapper(registry, hostlabels) + gw := NewGathererWrapper(registry, scrapeAllHostLabels(e.opts.NodeName)) gatherers = append(gatherers, gw) } @@ -172,6 +171,14 @@ func OverallTargetsHandler(exporters []*Exporter, logger *slog.Logger) http.Hand } } +func scrapeAllHostLabels(nodeName string) prometheus.Labels { + hostlabels := prometheus.Labels{} + if nodeName != "" { + hostlabels[scrapeAllInstanceLabel] = nodeName + } + return hostlabels +} + func buildServerMap(exporters []*Exporter, log *slog.Logger) ServerMap { servers := make(ServerMap, len(exporters)) for _, e := range exporters { diff --git a/exporter/server_test.go b/exporter/server_test.go new file mode 100644 index 000000000..9d091ec2e --- /dev/null +++ b/exporter/server_test.go @@ -0,0 +1,30 @@ +// mongodb_exporter +// Copyright (C) 2017 Percona LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package exporter + +import ( + "testing" + + "github.com/prometheus/client_golang/prometheus" + "github.com/stretchr/testify/assert" +) + +func TestScrapeAllHostLabels(t *testing.T) { + t.Parallel() + + assert.Equal(t, prometheus.Labels{}, scrapeAllHostLabels("")) + assert.Equal(t, prometheus.Labels{"mongo_instance": "node-a:27017"}, scrapeAllHostLabels("node-a:27017")) +}