Skip to content
Open
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions exporter/multi_target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
21 changes: 14 additions & 7 deletions exporter/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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"))
Expand Down Expand Up @@ -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)
}

Expand All @@ -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 {
Expand Down
30 changes: 30 additions & 0 deletions exporter/server_test.go
Original file line number Diff line number Diff line change
@@ -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"))
}