From 152b71acf5be93b664ba648268da2c0088793c4f Mon Sep 17 00:00:00 2001 From: adnull Date: Mon, 13 Feb 2023 23:54:35 +0300 Subject: [PATCH 01/20] added multi target feature --- exporter/exporter.go | 55 ++++++------------------------- exporter/server.go | 78 ++++++++++++++++++++++++++++++++++++++++++++ main.go | 70 ++++++++++++++++++++++++++------------- main_test.go | 7 ++-- 4 files changed, 139 insertions(+), 71 deletions(-) create mode 100644 exporter/server.go diff --git a/exporter/exporter.go b/exporter/exporter.go index 7807d4e9a..f84c8d5b2 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -22,15 +22,12 @@ import ( "fmt" "net/http" _ "net/http/pprof" - "os" "strconv" "sync" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/prometheus/common/promlog" - "github.com/prometheus/exporter-toolkit/web" "github.com/sirupsen/logrus" "go.mongodb.org/mongo-driver/mongo" @@ -39,12 +36,10 @@ import ( // Exporter holds Exporter methods and attributes. type Exporter struct { - path string client *mongo.Client clientMu sync.Mutex logger *logrus.Logger opts *Opts - webListenAddress string lock *sync.Mutex totalCollectionsCount int } @@ -73,10 +68,8 @@ type Opts struct { IndexStatsCollections []string Logger *logrus.Logger - Path string - URI string - WebListenAddress string - TLSConfigPath string + + URI string } var ( @@ -100,16 +93,9 @@ func New(opts *Opts) *Exporter { ctx := context.Background() - if opts.Path == "" { - opts.Logger.Warn("Web telemetry path \"\" invalid, falling back to \"/\" instead") - opts.Path = "/" - } - exp := &Exporter{ - path: opts.Path, logger: opts.Logger, opts: opts, - webListenAddress: opts.WebListenAddress, lock: &sync.Mutex{}, totalCollectionsCount: -1, // Not calculated yet. waiting the db connection. } @@ -311,14 +297,15 @@ func (e *Exporter) Handler() http.Handler { gatherers = append(gatherers, prometheus.DefaultGatherer) } + var ti *topologyInfo = nil if client != nil { // Topology can change between requests, so we need to get it every time. - ti := newTopologyInfo(ctx, client, e.logger) - - registry := e.makeRegistry(ctx, client, ti, requestOpts) - gatherers = append(gatherers, registry) + ti = newTopologyInfo(ctx, client, e.logger) } + registry := e.makeRegistry(ctx, client, ti, requestOpts) + gatherers = append(gatherers, registry) + // Delegate http serving to Prometheus client library, which will call collector.Collect. h := promhttp.HandlerFor(gatherers, promhttp.HandlerOpts{ ErrorHandling: promhttp.ContinueOnError, @@ -329,31 +316,6 @@ func (e *Exporter) Handler() http.Handler { }) } -// Run starts the exporter. -func (e *Exporter) Run() { - mux := http.DefaultServeMux - mux.Handle(e.path, e.Handler()) - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(` - MongoDB Exporter - -

MongoDB Exporter

-

Metrics

- - `)) - }) - - server := &http.Server{ - Addr: e.webListenAddress, - Handler: mux, - } - - if err := web.ListenAndServe(server, e.opts.TLSConfigPath, promlog.New(&promlog.Config{})); err != nil { - e.logger.Errorf("error starting server: %v", err) - os.Exit(1) - } -} - func connect(ctx context.Context, dsn string, directConnect bool) (*mongo.Client, error) { clientOpts, err := dsn_fix.ClientOptionsForDSN(dsn) if err != nil { @@ -361,8 +323,11 @@ func connect(ctx context.Context, dsn string, directConnect bool) (*mongo.Client } clientOpts.SetDirect(directConnect) clientOpts.SetAppName("mongodb_exporter") + clientOpts.SetConnectTimeout(9 * time.Second) + clientOpts.SetServerSelectionTimeout(9 * time.Second) client, err := mongo.Connect(ctx, clientOpts) + if err != nil { return nil, fmt.Errorf("invalid MongoDB options: %w", err) } diff --git a/exporter/server.go b/exporter/server.go new file mode 100644 index 000000000..d73a0f021 --- /dev/null +++ b/exporter/server.go @@ -0,0 +1,78 @@ +package exporter + +import ( + "net/http" + "net/url" + "os" + "strings" + + "github.com/prometheus/common/promlog" + "github.com/prometheus/exporter-toolkit/web" + "github.com/sirupsen/logrus" +) + +var ServerMap map[string]*Exporter + +type ServerOpts struct { + Path string + MultiTargetPath string + WebListenAddress string + TLSConfigPath string +} + +func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *logrus.Logger) { + mux := http.DefaultServeMux + + if len(exporters) == 0 { + panic("No exporters were builded. You must specify --mongodb.uri command argument or MONGODB_URI environment variable") + } + + serverMap := buildServerMap(exporters, log) + + defaultExporter := exporters[0] + mux.Handle(opts.Path, defaultExporter.Handler()) + mux.HandleFunc(opts.MultiTargetPath, func(w http.ResponseWriter, r *http.Request) { + targetHost := r.URL.Query().Get("target") + if targetHost != "" { + if !strings.HasPrefix(targetHost, "mongodb://") { + targetHost = "mongodb://" + targetHost + } + if uri, err := url.Parse(targetHost); err == nil { + if e, ok := serverMap[uri.Host]; ok { + e.ServeHTTP(w, r) + } + } + } + }) + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(` + MongoDB Exporter + +

MongoDB Exporter

+

Metrics

+ + `)) + }) + + server := &http.Server{ + Addr: opts.WebListenAddress, + Handler: mux, + } + + if err := web.ListenAndServe(server, opts.TLSConfigPath, promlog.New(&promlog.Config{})); err != nil { + log.Errorf("error starting server: %v", err) + os.Exit(1) + } +} + +func buildServerMap(exporters []*Exporter, log *logrus.Logger) map[string]http.Handler { + serverMap := make(map[string]http.Handler, len(exporters)) + for _, e := range exporters { + if url, err := url.Parse(e.opts.URI); err == nil { + serverMap[url.Host] = e.Handler() + } else { + log.Errorf("Unable to parse addr %s as url: %s", e.opts.URI, err) + } + } + return serverMap +} diff --git a/main.go b/main.go index 7d704565b..e96065181 100644 --- a/main.go +++ b/main.go @@ -35,15 +35,15 @@ var ( // GlobalFlags has command line flags to configure the exporter. type GlobalFlags struct { - CollStatsNamespaces string `name:"mongodb.collstats-colls" help:"List of comma separared databases.collections to get $collStats" placeholder:"db1,db2.col2"` - IndexStatsCollections string `name:"mongodb.indexstats-colls" help:"List of comma separared databases.collections to get $indexStats" placeholder:"db1.col1,db2.col2"` - URI string `name:"mongodb.uri" help:"MongoDB connection URI" env:"MONGODB_URI" placeholder:"mongodb://user:pass@127.0.0.1:27017/admin?ssl=true"` - GlobalConnPool bool `name:"mongodb.global-conn-pool" help:"Use global connection pool instead of creating new pool for each http request." negatable:""` - DirectConnect bool `name:"mongodb.direct-connect" help:"Whether or not a direct connect should be made. Direct connections are not valid if multiple hosts are specified or an SRV URI is used." default:"true" negatable:""` - WebListenAddress string `name:"web.listen-address" help:"Address to listen on for web interface and telemetry" default:":9216"` - WebTelemetryPath string `name:"web.telemetry-path" help:"Metrics expose path" default:"/metrics"` - TLSConfigPath string `name:"web.config" help:"Path to the file having Prometheus TLS config for basic auth"` - LogLevel string `name:"log.level" help:"Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]" enum:"debug,info,warn,error,fatal" default:"error"` + CollStatsNamespaces string `name:"mongodb.collstats-colls" help:"List of comma separared databases.collections to get $collStats" placeholder:"db1,db2.col2"` + IndexStatsCollections string `name:"mongodb.indexstats-colls" help:"List of comma separared databases.collections to get $indexStats" placeholder:"db1.col1,db2.col2"` + URI []string `name:"mongodb.uri" help:"MongoDB connection URI" env:"MONGODB_URI" placeholder:"mongodb://user:pass@127.0.0.1:27017/admin?ssl=true"` + GlobalConnPool bool `name:"mongodb.global-conn-pool" help:"Use global connection pool instead of creating new pool for each http request." negatable:""` + DirectConnect bool `name:"mongodb.direct-connect" help:"Whether or not a direct connect should be made. Direct connections are not valid if multiple hosts are specified or an SRV URI is used." default:"true" negatable:""` + WebListenAddress string `name:"web.listen-address" help:"Address to listen on for web interface and telemetry" default:":9216"` + WebTelemetryPath string `name:"web.telemetry-path" help:"Metrics expose path" default:"/metrics"` + TLSConfigPath string `name:"web.config" help:"Path to the file having Prometheus TLS config for basic auth"` + LogLevel string `name:"log.level" help:"Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]" enum:"debug,info,warn,error,fatal" default:"error"` EnableDiagnosticData bool `name:"collector.diagnosticdata" help:"Enable collecting metrics from getDiagnosticData"` EnableReplicasetStatus bool `name:"collector.replicasetstatus" help:"Enable collecting metrics from replSetGetStatus"` @@ -81,15 +81,9 @@ func main() { fmt.Printf("Version: %s\n", version) fmt.Printf("Commit: %s\n", commit) fmt.Printf("Build date: %s\n", buildDate) - return } - e := buildExporter(opts) - e.Run() -} - -func buildExporter(opts GlobalFlags) *exporter.Exporter { log := logrus.New() levels := map[string]logrus.Level{ @@ -103,12 +97,24 @@ func buildExporter(opts GlobalFlags) *exporter.Exporter { log.Debugf("Compatible mode: %v", opts.CompatibleMode) - if !strings.HasPrefix(opts.URI, "mongodb") { - log.Debugf("Prepending mongodb:// to the URI") - opts.URI = "mongodb://" + opts.URI + if opts.WebTelemetryPath == "" { + log.Warn("Web telemetry path \"\" invalid, falling back to \"/\" instead") + opts.WebTelemetryPath = "/" } - log.Debugf("Connection URI: %s", opts.URI) + serverOpts := &exporter.ServerOpts{ + Path: opts.WebTelemetryPath, + MultiTargetPath: "/scrape", + WebListenAddress: opts.WebListenAddress, + TLSConfigPath: opts.TLSConfigPath, + } + exporter.RunWebServer(serverOpts, buildServers(opts, log), log) + +} + +func buildExporter(opts GlobalFlags, uri string, log *logrus.Logger) *exporter.Exporter { + + log.Debugf("Connection URI: %s", uri) exporterOpts := &exporter.Opts{ CollStatsNamespaces: strings.Split(opts.CollStatsNamespaces, ","), @@ -116,11 +122,8 @@ func buildExporter(opts GlobalFlags) *exporter.Exporter { DiscoveringMode: opts.DiscoveringMode, IndexStatsCollections: strings.Split(opts.IndexStatsCollections, ","), Logger: log, - Path: opts.WebTelemetryPath, - URI: opts.URI, + URI: uri, GlobalConnPool: opts.GlobalConnPool, - WebListenAddress: opts.WebListenAddress, - TLSConfigPath: opts.TLSConfigPath, DirectConnect: opts.DirectConnect, EnableDiagnosticData: opts.EnableDiagnosticData, @@ -140,3 +143,24 @@ func buildExporter(opts GlobalFlags) *exporter.Exporter { return e } + +func buildServers(opts GlobalFlags, log *logrus.Logger) []*exporter.Exporter { + + var servers []*exporter.Exporter + + if len(opts.URI) == 1 { + opts.URI = strings.Split(opts.URI[0], " ") + } + for serverIdx := range opts.URI { + URI := opts.URI[serverIdx] + + if !strings.HasPrefix(URI, "mongodb") { + log.Debugf("Prepending mongodb:// to the URI %s", URI) + URI = "mongodb://" + URI + } + + servers = append(servers, buildExporter(opts, URI, log)) + } + + return servers +} diff --git a/main_test.go b/main_test.go index e11f468bd..4176fa4b6 100644 --- a/main_test.go +++ b/main_test.go @@ -18,13 +18,14 @@ package main import ( "testing" + + "github.com/sirupsen/logrus" ) func TestBuildExporter(t *testing.T) { opts := GlobalFlags{ CollStatsNamespaces: "c1,c2,c3", IndexStatsCollections: "i1,i2,i3", - URI: "mongodb://usr:pwd@127.0.0.1/", GlobalConnPool: false, // to avoid testing the connection WebListenAddress: "localhost:12345", WebTelemetryPath: "/mymetrics", @@ -35,6 +36,6 @@ func TestBuildExporter(t *testing.T) { CompatibleMode: true, } - - buildExporter(opts) + log := logrus.New() + buildExporter(opts, "mongodb://usr:pwd@127.0.0.1/", log) } From da9afc3978e55d33c1bc2345ce6e875f74b6fa52 Mon Sep 17 00:00:00 2001 From: ad Date: Sun, 7 May 2023 15:42:34 +0300 Subject: [PATCH 02/20] added connect timeout opts --- exporter/base_collector.go | 5 ++- exporter/exporter.go | 21 ++++++---- exporter/exporter_test.go | 78 ++++++++++++++++++++++++++++---------- main.go | 2 + 4 files changed, 78 insertions(+), 28 deletions(-) diff --git a/exporter/base_collector.go b/exporter/base_collector.go index c5d0f3a68..5e5e92c48 100644 --- a/exporter/base_collector.go +++ b/exporter/base_collector.go @@ -44,7 +44,10 @@ func newBaseCollector(client *mongo.Client, logger *logrus.Logger) *baseCollecto func (d *baseCollector) Describe(ctx context.Context, ch chan<- *prometheus.Desc, collect func(mCh chan<- prometheus.Metric)) { select { case <-ctx.Done(): - return + // don't interrupt, let mongodb_up metric to be registered if on timeout we still don't have client connected + if d.client != nil { + return + } default: } diff --git a/exporter/exporter.go b/exporter/exporter.go index 6011f7a26..1eb95574f 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -52,6 +52,7 @@ type Opts struct { CollStatsLimit int CompatibleMode bool DirectConnect bool + ConnectTimeoutMS int DisableDefaultRegistry bool DiscoveringMode bool GlobalConnPool bool @@ -223,7 +224,7 @@ func (e *Exporter) getClient(ctx context.Context) (*mongo.Client, error) { return e.client, nil } - client, err := connect(context.Background(), e.opts.URI, e.opts.DirectConnect) + client, err := connect(context.Background(), e.opts) if err != nil { return nil, err } @@ -233,7 +234,7 @@ func (e *Exporter) getClient(ctx context.Context) (*mongo.Client, error) { } // !e.opts.GlobalConnPool: create new client for every scrape. - client, err := connect(ctx, e.opts.URI, e.opts.DirectConnect) + client, err := connect(ctx, e.opts) if err != nil { return nil, err } @@ -331,15 +332,21 @@ func (e *Exporter) Handler() http.Handler { }) } -func connect(ctx context.Context, dsn string, directConnect bool) (*mongo.Client, error) { - clientOpts, err := dsn_fix.ClientOptionsForDSN(dsn) +func connect(ctx context.Context, opts *Opts) (*mongo.Client, error) { + + clientOpts, err := dsn_fix.ClientOptionsForDSN(opts.URI) if err != nil { return nil, fmt.Errorf("invalid dsn: %w", err) } - clientOpts.SetDirect(directConnect) + + clientOpts.SetDirect(opts.DirectConnect) clientOpts.SetAppName("mongodb_exporter") - clientOpts.SetConnectTimeout(9 * time.Second) - clientOpts.SetServerSelectionTimeout(9 * time.Second) + + if clientOpts.ConnectTimeout == nil { + connectTimeoutMS := time.Duration(opts.ConnectTimeoutMS) * time.Millisecond + clientOpts.SetConnectTimeout(connectTimeoutMS) + clientOpts.SetServerSelectionTimeout(connectTimeoutMS) + } client, err := mongo.Connect(ctx, clientOpts) diff --git a/exporter/exporter_test.go b/exporter/exporter_test.go index fd3444900..dece44ec9 100644 --- a/exporter/exporter_test.go +++ b/exporter/exporter_test.go @@ -62,8 +62,11 @@ func TestConnect(t *testing.T) { t.Run("Connect without SSL", func(t *testing.T) { for name, port := range ports { - dsn := fmt.Sprintf("mongodb://%s:%s/admin", hostname, port) - client, err := connect(ctx, dsn, true) + exporterOpts := &Opts{ + URI: fmt.Sprintf("mongodb://%s:%s/admin", hostname, port), + DirectConnect: true, + } + client, err := connect(ctx, exporterOpts) assert.NoError(t, err, name) err = client.Disconnect(ctx) assert.NoError(t, err, name) @@ -168,17 +171,17 @@ func TestMongoS(t *testing.T) { } for _, test := range tests { - dsn := fmt.Sprintf("mongodb://%s:%s/admin", hostname, test.port) - client, err := connect(ctx, dsn, true) - assert.NoError(t, err) - exporterOpts := &Opts{ Logger: logrus.New(), - URI: dsn, + URI: fmt.Sprintf("mongodb://%s:%s/admin", hostname, test.port), + DirectConnect: true, GlobalConnPool: false, EnableReplicasetStatus: true, } + client, err := connect(ctx, exporterOpts) + assert.NoError(t, err) + e := New(exporterOpts) rsgsc := newReplicationSetStatusCollector(ctx, client, e.opts.Logger, @@ -196,23 +199,58 @@ func TestMongoS(t *testing.T) { func TestMongoUp(t *testing.T) { ctx := context.Background() - dsn := "mongodb://127.0.0.1:123456/admin" - client, err := connect(ctx, dsn, true) - assert.Error(t, err) + type testcase struct { + URI string + Want int + } - exporterOpts := &Opts{ - Logger: logrus.New(), - URI: dsn, - GlobalConnPool: false, - CollectAll: true, + testCases := []testcase{ + {URI: "mongodb://127.0.0.1:12345/admin", Want: 0}, + {URI: fmt.Sprintf("mongodb://127.0.0.1:%s/admin", tu.GetenvDefault("TEST_MONGODB_STANDALONE_PORT", "27017")), Want: 1}, } - e := New(exporterOpts) + for _, tc := range testCases { + exporterOpts := &Opts{ + Logger: logrus.New(), + URI: tc.URI, + ConnectTimeoutMS: 200, + DirectConnect: true, + GlobalConnPool: false, + CollectAll: true, + } - gc := newGeneralCollector(ctx, client, e.opts.Logger) + client, err := connect(ctx, exporterOpts) + if tc.Want == 1 { + assert.NoError(t, err, "Must be able to connect to %s", tc.URI) + } else { + assert.Error(t, err, "Must be unable to connect to %s", tc.URI) + } - r := e.makeRegistry(ctx, client, new(labelsGetterMock), *e.opts) + e := New(exporterOpts) - res := r.Unregister(gc) - assert.Equal(t, true, res) + gc := newGeneralCollector(ctx, client, e.opts.Logger) + + r := e.makeRegistry(ctx, client, new(labelsGetterMock), *e.opts) + mfs, err := r.Gather() + assert.NoError(t, err) + + mongo_metric_exists := false + mongo_up := 0 + for _, mf := range mfs { + if mf.GetName() == "mongodb_up" { + mongo_metric_exists = true + for _, m := range mf.GetMetric() { + if m.GetGauge().GetValue() == 1 { + mongo_up = 1 + } + } + } + } + + assert.True(t, mongo_metric_exists, "mongodb_up metric must exists in the registry") + assert.EqualValues(t, tc.Want, mongo_up, "mongodb_up metric must be %d in for %s", tc.Want, tc.URI) + + res := r.Unregister(gc) + assert.Equal(t, true, res) + } } diff --git a/main.go b/main.go index e96065181..86d44e668 100644 --- a/main.go +++ b/main.go @@ -44,6 +44,7 @@ type GlobalFlags struct { WebTelemetryPath string `name:"web.telemetry-path" help:"Metrics expose path" default:"/metrics"` TLSConfigPath string `name:"web.config" help:"Path to the file having Prometheus TLS config for basic auth"` LogLevel string `name:"log.level" help:"Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]" enum:"debug,info,warn,error,fatal" default:"error"` + ConnectTimeoutMS int `name:"mongodb.connect-timeout-ms" help:"Connection timeout in milliseconds" default:"5000"` EnableDiagnosticData bool `name:"collector.diagnosticdata" help:"Enable collecting metrics from getDiagnosticData"` EnableReplicasetStatus bool `name:"collector.replicasetstatus" help:"Enable collecting metrics from replSetGetStatus"` @@ -125,6 +126,7 @@ func buildExporter(opts GlobalFlags, uri string, log *logrus.Logger) *exporter.E URI: uri, GlobalConnPool: opts.GlobalConnPool, DirectConnect: opts.DirectConnect, + ConnectTimeoutMS: opts.ConnectTimeoutMS, EnableDiagnosticData: opts.EnableDiagnosticData, EnableReplicasetStatus: opts.EnableReplicasetStatus, From 4e861b60054f3e12e0a57877de82349f24ba66ce Mon Sep 17 00:00:00 2001 From: ad Date: Sun, 7 May 2023 19:43:58 +0300 Subject: [PATCH 03/20] added tests --- exporter/exporter_test.go | 53 +++++++++++++++++--------- exporter/multi_target_test.go | 70 +++++++++++++++++++++++++++++++++++ exporter/server.go | 34 +++++++++-------- 3 files changed, 124 insertions(+), 33 deletions(-) create mode 100644 exporter/multi_target_test.go diff --git a/exporter/exporter_test.go b/exporter/exporter_test.go index dece44ec9..e941deb4f 100644 --- a/exporter/exporter_test.go +++ b/exporter/exporter_test.go @@ -22,9 +22,12 @@ import ( "io/ioutil" "net/http" "net/http/httptest" + "strconv" + "strings" "sync" "testing" + "github.com/prometheus/client_golang/prometheus/testutil" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" @@ -199,6 +202,30 @@ func TestMongoS(t *testing.T) { func TestMongoUp(t *testing.T) { ctx := context.Background() + exporterOpts := &Opts{ + Logger: logrus.New(), + URI: "mongodb://127.0.0.1:123456/admin", + DirectConnect: true, + GlobalConnPool: false, + CollectAll: true, + } + + client, err := connect(ctx, exporterOpts) + assert.Error(t, err) + + e := New(exporterOpts) + + gc := newGeneralCollector(ctx, client, e.opts.Logger) + + r := e.makeRegistry(ctx, client, new(labelsGetterMock), *e.opts) + + res := r.Unregister(gc) + assert.Equal(t, true, res) +} + +func TestMongoUpMetric(t *testing.T) { + ctx := context.Background() + type testcase struct { URI string Want int @@ -227,28 +254,18 @@ func TestMongoUp(t *testing.T) { } e := New(exporterOpts) - gc := newGeneralCollector(ctx, client, e.opts.Logger) - r := e.makeRegistry(ctx, client, new(labelsGetterMock), *e.opts) - mfs, err := r.Gather() - assert.NoError(t, err) - mongo_metric_exists := false - mongo_up := 0 - for _, mf := range mfs { - if mf.GetName() == "mongodb_up" { - mongo_metric_exists = true - for _, m := range mf.GetMetric() { - if m.GetGauge().GetValue() == 1 { - mongo_up = 1 - } - } - } + expected := strings.NewReader(` + # HELP mongodb_up Whether MongoDB is up. + # TYPE mongodb_up gauge + mongodb_up ` + strconv.Itoa(tc.Want) + "\n") + filter := []string{ + "mongodb_up", } - - assert.True(t, mongo_metric_exists, "mongodb_up metric must exists in the registry") - assert.EqualValues(t, tc.Want, mongo_up, "mongodb_up metric must be %d in for %s", tc.Want, tc.URI) + err = testutil.CollectAndCompare(gc, expected, filter...) + assert.NoError(t, err, "mongodb_up metric should be %d", tc.Want) res := r.Unregister(gc) assert.Equal(t, true, res) diff --git a/exporter/multi_target_test.go b/exporter/multi_target_test.go new file mode 100644 index 000000000..886997ab1 --- /dev/null +++ b/exporter/multi_target_test.go @@ -0,0 +1,70 @@ +// mongodb_exporter +// Copyright (C) 2017 Percona LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package exporter + +import ( + "fmt" + "net/http" + "testing" + + "github.com/percona/mongodb_exporter/internal/tu" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" +) + +func TestMultiTarget(t *testing.T) { + var exporters []*Exporter + opts := []*Opts{ + { + URI: fmt.Sprintf("mongodb://%s:%s", "127.0.0.1", tu.GetenvDefault("TEST_MONGODB_STANDALONE_PORT", "27017")), + DirectConnect: true, + ConnectTimeoutMS: 1000, + }, + { + URI: fmt.Sprintf("mongodb://%s:%s", "127.0.0.1", tu.GetenvDefault("TEST_MONGODB_S1_PRIMARY_PORT", "17001")), + DirectConnect: true, + ConnectTimeoutMS: 1000, + }, + { + URI: fmt.Sprintf("mongodb://%s:%s", "127.0.0.1", tu.GetenvDefault("TEST_MONGODB_S2_PRIMARY_PORT", "17004")), + DirectConnect: true, + ConnectTimeoutMS: 1000, + }, + { + URI: fmt.Sprintf("mongodb://%s:%s", "127.0.0.1", "12345"), + DirectConnect: true, + ConnectTimeoutMS: 1000, + }, + } + for _, opt := range opts { + exporters = append(exporters, New(opt)) + } + log := logrus.New() + ServerMap = buildServerMap(exporters, log) + + expected := []string{ + "mongodb_up 1\n", + "mongodb_up 1\n", + "mongodb_up 1\n", + "mongodb_up 1\n", + } + + // Test all targets + for sn, opt := range opts { + assert.HTTPBodyContains(t, http.HandlerFunc(multiTargetHandler), "GET", fmt.Sprintf("?target=%s", opt.URI), nil, expected[sn]) + } +} diff --git a/exporter/server.go b/exporter/server.go index d73a0f021..2ce625fc9 100644 --- a/exporter/server.go +++ b/exporter/server.go @@ -11,7 +11,7 @@ import ( "github.com/sirupsen/logrus" ) -var ServerMap map[string]*Exporter +var ServerMap map[string]http.Handler type ServerOpts struct { Path string @@ -27,23 +27,11 @@ func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *logrus.Logger) { panic("No exporters were builded. You must specify --mongodb.uri command argument or MONGODB_URI environment variable") } - serverMap := buildServerMap(exporters, log) + ServerMap = buildServerMap(exporters, log) defaultExporter := exporters[0] mux.Handle(opts.Path, defaultExporter.Handler()) - mux.HandleFunc(opts.MultiTargetPath, func(w http.ResponseWriter, r *http.Request) { - targetHost := r.URL.Query().Get("target") - if targetHost != "" { - if !strings.HasPrefix(targetHost, "mongodb://") { - targetHost = "mongodb://" + targetHost - } - if uri, err := url.Parse(targetHost); err == nil { - if e, ok := serverMap[uri.Host]; ok { - e.ServeHTTP(w, r) - } - } - } - }) + mux.HandleFunc(opts.MultiTargetPath, multiTargetHandler) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(` MongoDB Exporter @@ -65,6 +53,22 @@ func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *logrus.Logger) { } } +func multiTargetHandler(w http.ResponseWriter, r *http.Request) { + targetHost := r.URL.Query().Get("target") + if targetHost != "" { + if !strings.HasPrefix(targetHost, "mongodb://") { + targetHost = "mongodb://" + targetHost + } + if uri, err := url.Parse(targetHost); err == nil { + if e, ok := ServerMap[uri.Host]; ok { + e.ServeHTTP(w, r) + return + } + } + } + http.Error(w, "Unable to find target", http.StatusNotFound) +} + func buildServerMap(exporters []*Exporter, log *logrus.Logger) map[string]http.Handler { serverMap := make(map[string]http.Handler, len(exporters)) for _, e := range exporters { From b7c58c320faea6ba355183b71f45dddc52c75116 Mon Sep 17 00:00:00 2001 From: ad Date: Sun, 7 May 2023 20:21:56 +0300 Subject: [PATCH 04/20] fixed test --- exporter/multi_target_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/multi_target_test.go b/exporter/multi_target_test.go index 886997ab1..ab1c9aee8 100644 --- a/exporter/multi_target_test.go +++ b/exporter/multi_target_test.go @@ -60,7 +60,7 @@ func TestMultiTarget(t *testing.T) { "mongodb_up 1\n", "mongodb_up 1\n", "mongodb_up 1\n", - "mongodb_up 1\n", + "mongodb_up 0\n", } // Test all targets From c8cadf13f5d3628abe0753935ab6ddb79c35708d Mon Sep 17 00:00:00 2001 From: ad Date: Sun, 7 May 2023 23:19:28 +0300 Subject: [PATCH 05/20] fixed dockerfile --- Dockerfile | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3ed6f8ffb..759ab614a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,18 @@ FROM alpine AS builder RUN apk add --no-cache ca-certificates -FROM scratch AS final +FROM golang:alpine as builder2 + +RUN apk update && apk add make +RUN mkdir /source +COPY . /source +WORKDIR /source +RUN make init +RUN make build + +FROM alpine AS final USER 65535:65535 -COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ -COPY ./mongodb_exporter / +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +COPY --from=builder2 /source/mongodb_exporter / EXPOSE 9216 ENTRYPOINT ["/mongodb_exporter"] \ No newline at end of file From 70421c4fb249f5f99c310069afe48f4c09f00e3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 May 2023 17:19:08 +0200 Subject: [PATCH 06/20] Bump github.com/golangci/golangci-lint from 1.47.3 to 1.52.2 in /tools (#639) Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.47.3 to 1.52.2. - [Release notes](https://github.com/golangci/golangci-lint/releases) - [Changelog](https://github.com/golangci/golangci-lint/blob/master/CHANGELOG.md) - [Commits](https://github.com/golangci/golangci-lint/compare/v1.47.3...v1.52.2) --- updated-dependencies: - dependency-name: github.com/golangci/golangci-lint dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/go.sum | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/go.sum b/tools/go.sum index 2b6bc7bbb..184ccc67f 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -550,6 +550,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/junk1tm/musttag v0.5.0 h1:bV1DTdi38Hi4pG4OVWa7Kap0hi0o7EczuK6wQt9zPOM= +github.com/junk1tm/musttag v0.5.0/go.mod h1:PcR7BA+oREQYvHwgjIDmw3exJeds5JzRcvEJTfjrA0M= github.com/justinas/nosurf v1.1.1/go.mod h1:ALpWdSbuNGy2lZWtyXdjkYv4edL23oSEgfBT1gPJ5BQ= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= From 2b5eb69694f506e9c862358abf95160e961b0afc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:35:25 +0300 Subject: [PATCH 07/20] Bump github.com/golangci/golangci-lint from 1.52.2 to 1.53.2 in /tools (#665) Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.52.2 to 1.53.2. - [Release notes](https://github.com/golangci/golangci-lint/releases) - [Changelog](https://github.com/golangci/golangci-lint/blob/master/CHANGELOG.md) - [Commits](https://github.com/golangci/golangci-lint/compare/v1.52.2...v1.53.2) --- updated-dependencies: - dependency-name: github.com/golangci/golangci-lint dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/go.sum b/tools/go.sum index 184ccc67f..2b6bc7bbb 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -550,8 +550,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= -github.com/junk1tm/musttag v0.5.0 h1:bV1DTdi38Hi4pG4OVWa7Kap0hi0o7EczuK6wQt9zPOM= -github.com/junk1tm/musttag v0.5.0/go.mod h1:PcR7BA+oREQYvHwgjIDmw3exJeds5JzRcvEJTfjrA0M= github.com/justinas/nosurf v1.1.1/go.mod h1:ALpWdSbuNGy2lZWtyXdjkYv4edL23oSEgfBT1gPJ5BQ= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= From 89d0a7e08eb4d938fd84593df3ff074e4df04bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Tudur=C3=AD?= Date: Thu, 6 Jul 2023 11:23:07 +0200 Subject: [PATCH 08/20] Remove `prometheus/client_golang` replace (#682) * Remove prometheus/client_golang replace * Apply formater * Downgrade client_golang to previous version * Upgrade exporter-toolkit to v0.10.0 --- exporter/collstats_collector.go | 2 +- exporter/dbstats_collector.go | 2 +- exporter/diagnostic_data_collector.go | 2 +- exporter/exporter_metrics.go | 43 ++++++++++++++ exporter/general_collector.go | 2 +- exporter/indexstats_collector.go | 2 +- exporter/replset_status_collector.go | 2 +- exporter/top_collector.go | 2 +- go.mod | 40 ++++++------- go.sum | 86 +++++++++++---------------- 10 files changed, 103 insertions(+), 80 deletions(-) create mode 100644 exporter/exporter_metrics.go diff --git a/exporter/collstats_collector.go b/exporter/collstats_collector.go index 6e822f7fe..3ad56b42d 100644 --- a/exporter/collstats_collector.go +++ b/exporter/collstats_collector.go @@ -59,7 +59,7 @@ func (d *collstatsCollector) Collect(ch chan<- prometheus.Metric) { } func (d *collstatsCollector) collect(ch chan<- prometheus.Metric) { - defer prometheus.MeasureCollectTime(ch, "mongodb", "collstats")() + defer measureCollectTime(ch, "mongodb", "collstats")() collections := d.collections diff --git a/exporter/dbstats_collector.go b/exporter/dbstats_collector.go index bc3210971..a8aad3948 100644 --- a/exporter/dbstats_collector.go +++ b/exporter/dbstats_collector.go @@ -56,7 +56,7 @@ func (d *dbstatsCollector) Collect(ch chan<- prometheus.Metric) { } func (d *dbstatsCollector) collect(ch chan<- prometheus.Metric) { - defer prometheus.MeasureCollectTime(ch, "mongodb", "dbstats")() + defer measureCollectTime(ch, "mongodb", "dbstats")() logger := d.base.logger client := d.base.client diff --git a/exporter/diagnostic_data_collector.go b/exporter/diagnostic_data_collector.go index b7027abf4..160af1882 100644 --- a/exporter/diagnostic_data_collector.go +++ b/exporter/diagnostic_data_collector.go @@ -59,7 +59,7 @@ func (d *diagnosticDataCollector) Collect(ch chan<- prometheus.Metric) { } func (d *diagnosticDataCollector) collect(ch chan<- prometheus.Metric) { - defer prometheus.MeasureCollectTime(ch, "mongodb", "diagnostic_data")() + defer measureCollectTime(ch, "mongodb", "diagnostic_data")() var m bson.M diff --git a/exporter/exporter_metrics.go b/exporter/exporter_metrics.go new file mode 100644 index 000000000..edba2b1db --- /dev/null +++ b/exporter/exporter_metrics.go @@ -0,0 +1,43 @@ +// mongodb_exporter +// Copyright (C) 2022 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 ( + "time" + + "github.com/prometheus/client_golang/prometheus" +) + +// measureCollectTime measures time taken for scrape by collector +func measureCollectTime(ch chan<- prometheus.Metric, exporter, collector string) func() { + startTime := time.Now() + timeToCollectDesc := prometheus.NewDesc( + "collector_scrape_time_ms", + "Time taken for scrape by collector", + []string{"exporter"}, + prometheus.Labels{"collector": collector}, // to have ID calculated correctly + ) + + return func() { + scrapeTime := time.Since(startTime) + scrapeMetric := prometheus.MustNewConstMetric( + timeToCollectDesc, + prometheus.GaugeValue, + float64(scrapeTime.Milliseconds()), + exporter) + ch <- scrapeMetric + } +} diff --git a/exporter/general_collector.go b/exporter/general_collector.go index 2a993c7fe..6cfd62864 100644 --- a/exporter/general_collector.go +++ b/exporter/general_collector.go @@ -48,7 +48,7 @@ func (d *generalCollector) Collect(ch chan<- prometheus.Metric) { } func (d *generalCollector) collect(ch chan<- prometheus.Metric) { - defer prometheus.MeasureCollectTime(ch, "mongodb", "general")() + defer measureCollectTime(ch, "mongodb", "general")() ch <- mongodbUpMetric(d.ctx, d.base.client, d.base.logger) } diff --git a/exporter/indexstats_collector.go b/exporter/indexstats_collector.go index 946b4afba..9f75bf2db 100644 --- a/exporter/indexstats_collector.go +++ b/exporter/indexstats_collector.go @@ -60,7 +60,7 @@ func (d *indexstatsCollector) Collect(ch chan<- prometheus.Metric) { } func (d *indexstatsCollector) collect(ch chan<- prometheus.Metric) { - defer prometheus.MeasureCollectTime(ch, "mongodb", "indexstats")() + defer measureCollectTime(ch, "mongodb", "indexstats")() collections := d.collections diff --git a/exporter/replset_status_collector.go b/exporter/replset_status_collector.go index 25fb5bfa4..65e9ceb7e 100644 --- a/exporter/replset_status_collector.go +++ b/exporter/replset_status_collector.go @@ -57,7 +57,7 @@ func (d *replSetGetStatusCollector) Collect(ch chan<- prometheus.Metric) { } func (d *replSetGetStatusCollector) collect(ch chan<- prometheus.Metric) { - defer prometheus.MeasureCollectTime(ch, "mongodb", "replset_status")() + defer measureCollectTime(ch, "mongodb", "replset_status")() logger := d.base.logger client := d.base.client diff --git a/exporter/top_collector.go b/exporter/top_collector.go index a06da6a91..e40f0a447 100644 --- a/exporter/top_collector.go +++ b/exporter/top_collector.go @@ -56,7 +56,7 @@ func (d *topCollector) Collect(ch chan<- prometheus.Metric) { } func (d *topCollector) collect(ch chan<- prometheus.Metric) { - defer prometheus.MeasureCollectTime(ch, "mongodb", "top")() + defer measureCollectTime(ch, "mongodb", "top")() logger := d.base.logger client := d.base.client diff --git a/go.mod b/go.mod index 910b9b90a..3e7cb571c 100644 --- a/go.mod +++ b/go.mod @@ -2,21 +2,16 @@ module github.com/percona/mongodb_exporter go 1.19 -// Update percona-toolkit with `go get -v github.com/percona/percona-toolkit@3.0; go mod tidy` (without `-u`) -// until we have everything we need in a tagged release. - -replace github.com/prometheus/client_golang v1.12.2 => github.com/Percona-Lab/client_golang v1.12.2-0.20220701073455-ee06569fd6a5 - require ( github.com/AlekSi/pointer v1.1.0 github.com/alecthomas/kong v0.8.0 github.com/golang/snappy v0.0.3 // indirect github.com/percona/exporter_shared v0.7.4-0.20211108113423-8555cdbac68b github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.12.2 + github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.4.0 - github.com/prometheus/common v0.37.0 - github.com/prometheus/exporter-toolkit v0.7.2 + github.com/prometheus/common v0.42.0 + github.com/prometheus/exporter-toolkit v0.10.0 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.8.2 go.mongodb.org/mongo-driver v1.11.7 @@ -24,34 +19,33 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-kit/log v0.2.0 // indirect + github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/klauspost/compress v1.13.6 // indirect - github.com/kr/pretty v0.3.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/procfs v0.10.1 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.1 // indirect github.com/xdg-go/stringprep v1.0.3 // indirect github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect - golang.org/x/crypto v0.1.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.8.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/sync v0.2.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ba97163ee..07037683a 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,6 @@ github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Percona-Lab/client_golang v1.12.2-0.20220701073455-ee06569fd6a5 h1:lDRQDHeClQgTRzllGb2R9SSqF/Y9EDtutT5EXDDdyZ4= -github.com/Percona-Lab/client_golang v1.12.2-0.20220701073455-ee06569fd6a5/go.mod h1:obkGjwg6Wf+MW4GSHajtE/Krl1VzvajWi2ruzjqNk1k= github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0= github.com/alecthomas/kong v0.8.0 h1:ryDCzutfIqJPnNn0omnrgHLbAggDQM2VWHikE1xqK7s= github.com/alecthomas/kong v0.8.0/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= @@ -52,13 +50,15 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -73,14 +73,15 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0 h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -108,8 +109,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -125,8 +126,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -149,7 +149,6 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -161,26 +160,23 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/percona/exporter_shared v0.7.4-0.20211108113423-8555cdbac68b h1:tPnodYuNto6iPkeBCKJKw2HLeEYCiRmN2cpcMzTs8W4= github.com/percona/exporter_shared v0.7.4-0.20211108113423-8555cdbac68b/go.mod h1:bweWrCdYX+iAONTNUNIIkXGDjGg8dbFL0VBxuUv0wus= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -193,7 +189,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -203,22 +200,20 @@ github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.31.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/exporter-toolkit v0.7.2 h1:O7dcXagEAkXNSU6f3uXYqrhIjHArvxVeGAm0YGctino= -github.com/prometheus/exporter-toolkit v0.7.2/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/exporter-toolkit v0.10.0 h1:yOAzZTi4M22ZzVxD+fhy1URTuNRj/36uQJJ5S8IPza8= +github.com/prometheus/exporter-toolkit v0.10.0/go.mod h1:+sVFzuvV5JDyw+Ih6p3zFxZNVnKQa3x5qPmDSiPu4ZY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -263,10 +258,9 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -325,22 +319,18 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 h1:+jnHzr9VPj32ykQVai5DNahi9+NSp7yYuCsl5eAQtL0= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -351,8 +341,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -389,13 +379,10 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -403,8 +390,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -535,8 +522,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 4f1d85e9051e502ac8415fb74f6997c0b642dbe9 Mon Sep 17 00:00:00 2001 From: adnull Date: Mon, 13 Feb 2023 23:54:35 +0300 Subject: [PATCH 09/20] added multi target feature --- exporter/exporter.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exporter/exporter.go b/exporter/exporter.go index fa5138239..4aef6248c 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -339,6 +339,8 @@ func connect(ctx context.Context, opts *Opts) (*mongo.Client, error) { clientOpts.SetDirect(opts.DirectConnect) clientOpts.SetAppName("mongodb_exporter") + clientOpts.SetConnectTimeout(9 * time.Second) + clientOpts.SetServerSelectionTimeout(9 * time.Second) if clientOpts.ConnectTimeout == nil { connectTimeoutMS := time.Duration(opts.ConnectTimeoutMS) * time.Millisecond From 065a84787fb53bb24841fc6147e38153eca5e143 Mon Sep 17 00:00:00 2001 From: ad Date: Sun, 7 May 2023 15:42:34 +0300 Subject: [PATCH 10/20] added connect timeout opts --- exporter/exporter.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/exporter/exporter.go b/exporter/exporter.go index 4aef6248c..b54af4ad9 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -339,8 +339,12 @@ func connect(ctx context.Context, opts *Opts) (*mongo.Client, error) { clientOpts.SetDirect(opts.DirectConnect) clientOpts.SetAppName("mongodb_exporter") - clientOpts.SetConnectTimeout(9 * time.Second) - clientOpts.SetServerSelectionTimeout(9 * time.Second) + + if clientOpts.ConnectTimeout == nil { + connectTimeoutMS := time.Duration(opts.ConnectTimeoutMS) * time.Millisecond + clientOpts.SetConnectTimeout(connectTimeoutMS) + clientOpts.SetServerSelectionTimeout(connectTimeoutMS) + } if clientOpts.ConnectTimeout == nil { connectTimeoutMS := time.Duration(opts.ConnectTimeoutMS) * time.Millisecond From 4a01d30683eec42bcc28cacac591aa3d48374e07 Mon Sep 17 00:00:00 2001 From: ad Date: Thu, 6 Jul 2023 14:57:35 +0300 Subject: [PATCH 11/20] fixed connect --- exporter/server.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/exporter/server.go b/exporter/server.go index 2ce625fc9..b04818246 100644 --- a/exporter/server.go +++ b/exporter/server.go @@ -43,11 +43,13 @@ func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *logrus.Logger) { }) server := &http.Server{ - Addr: opts.WebListenAddress, Handler: mux, } - - if err := web.ListenAndServe(server, opts.TLSConfigPath, promlog.New(&promlog.Config{})); err != nil { + flags := &web.FlagConfig{ + WebListenAddresses: &[]string{opts.WebListenAddress}, + WebConfigFile: &opts.TLSConfigPath, + } + if err := web.ListenAndServe(server, flags, promlog.New(&promlog.Config{})); err != nil { log.Errorf("error starting server: %v", err) os.Exit(1) } From 3241789101e3a2d23154acfce3afe1ac591b4630 Mon Sep 17 00:00:00 2001 From: adnull Date: Thu, 3 Aug 2023 20:10:02 +0300 Subject: [PATCH 12/20] formatted code --- exporter/exporter.go | 2 -- exporter/multi_target_test.go | 3 ++- main.go | 3 --- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/exporter/exporter.go b/exporter/exporter.go index b54af4ad9..9cc7698b4 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -331,7 +331,6 @@ func (e *Exporter) Handler() http.Handler { } func connect(ctx context.Context, opts *Opts) (*mongo.Client, error) { - clientOpts, err := dsn_fix.ClientOptionsForDSN(opts.URI) if err != nil { return nil, fmt.Errorf("invalid dsn: %w", err) @@ -353,7 +352,6 @@ func connect(ctx context.Context, opts *Opts) (*mongo.Client, error) { } client, err := mongo.Connect(ctx, clientOpts) - if err != nil { return nil, fmt.Errorf("invalid MongoDB options: %w", err) } diff --git a/exporter/multi_target_test.go b/exporter/multi_target_test.go index ab1c9aee8..72031b7ee 100644 --- a/exporter/multi_target_test.go +++ b/exporter/multi_target_test.go @@ -21,9 +21,10 @@ import ( "net/http" "testing" - "github.com/percona/mongodb_exporter/internal/tu" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" + + "github.com/percona/mongodb_exporter/internal/tu" ) func TestMultiTarget(t *testing.T) { diff --git a/main.go b/main.go index 56c68a5be..228b1f3f8 100644 --- a/main.go +++ b/main.go @@ -109,11 +109,9 @@ func main() { TLSConfigPath: opts.TLSConfigPath, } exporter.RunWebServer(serverOpts, buildServers(opts, log), log) - } func buildExporter(opts GlobalFlags, uri string, log *logrus.Logger) *exporter.Exporter { - log.Debugf("Connection URI: %s", uri) exporterOpts := &exporter.Opts{ @@ -146,7 +144,6 @@ func buildExporter(opts GlobalFlags, uri string, log *logrus.Logger) *exporter.E } func buildServers(opts GlobalFlags, log *logrus.Logger) []*exporter.Exporter { - var servers []*exporter.Exporter if len(opts.URI) == 1 { From a8d48e853f04def941e427b808f3689802757e88 Mon Sep 17 00:00:00 2001 From: ad Date: Tue, 8 Aug 2023 23:20:58 +0300 Subject: [PATCH 13/20] fixed linter warnings --- exporter/exporter.go | 14 +++++++------- exporter/exporter_test.go | 5 +++-- exporter/multi_target_test.go | 19 +++++++++++-------- exporter/server.go | 20 ++++++++++++++------ main.go | 7 ++++--- 5 files changed, 39 insertions(+), 26 deletions(-) diff --git a/exporter/exporter.go b/exporter/exporter.go index 9cc7698b4..19bd2db0d 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -311,7 +311,7 @@ func (e *Exporter) Handler() http.Handler { gatherers = append(gatherers, prometheus.DefaultGatherer) } - var ti *topologyInfo = nil + var ti *topologyInfo if client != nil { // Topology can change between requests, so we need to get it every time. ti = newTopologyInfo(ctx, client, e.logger) @@ -340,15 +340,15 @@ func connect(ctx context.Context, opts *Opts) (*mongo.Client, error) { clientOpts.SetAppName("mongodb_exporter") if clientOpts.ConnectTimeout == nil { - connectTimeoutMS := time.Duration(opts.ConnectTimeoutMS) * time.Millisecond - clientOpts.SetConnectTimeout(connectTimeoutMS) - clientOpts.SetServerSelectionTimeout(connectTimeoutMS) + connectTimeout := time.Duration(opts.ConnectTimeoutMS) * time.Millisecond + clientOpts.SetConnectTimeout(connectTimeout) + clientOpts.SetServerSelectionTimeout(connectTimeout) } if clientOpts.ConnectTimeout == nil { - connectTimeoutMS := time.Duration(opts.ConnectTimeoutMS) * time.Millisecond - clientOpts.SetConnectTimeout(connectTimeoutMS) - clientOpts.SetServerSelectionTimeout(connectTimeoutMS) + connectTimeout := time.Duration(opts.ConnectTimeoutMS) * time.Millisecond + clientOpts.SetConnectTimeout(connectTimeout) + clientOpts.SetServerSelectionTimeout(connectTimeout) } client, err := mongo.Connect(ctx, clientOpts) diff --git a/exporter/exporter_test.go b/exporter/exporter_test.go index b8d01af16..9dba21159 100644 --- a/exporter/exporter_test.go +++ b/exporter/exporter_test.go @@ -19,6 +19,7 @@ import ( "context" "fmt" "io" + "net" "net/http" "net/http/httptest" "strconv" @@ -65,7 +66,7 @@ func TestConnect(t *testing.T) { t.Run("Connect without SSL", func(t *testing.T) { for name, port := range ports { exporterOpts := &Opts{ - URI: fmt.Sprintf("mongodb://%s:%s/admin", hostname, port), + URI: fmt.Sprintf("mongodb://%s/admin", net.JoinHostPort(hostname, port)), DirectConnect: true, } client, err := connect(ctx, exporterOpts) @@ -175,7 +176,7 @@ func TestMongoS(t *testing.T) { for _, test := range tests { exporterOpts := &Opts{ Logger: logrus.New(), - URI: fmt.Sprintf("mongodb://%s:%s/admin", hostname, test.port), + URI: fmt.Sprintf("mongodb://%s/admin", net.JoinHostPort(hostname, test.port)), DirectConnect: true, GlobalConnPool: false, EnableReplicasetStatus: true, diff --git a/exporter/multi_target_test.go b/exporter/multi_target_test.go index 72031b7ee..612d68d6e 100644 --- a/exporter/multi_target_test.go +++ b/exporter/multi_target_test.go @@ -18,6 +18,7 @@ package exporter import ( "fmt" + "net" "net/http" "testing" @@ -28,34 +29,36 @@ import ( ) func TestMultiTarget(t *testing.T) { - var exporters []*Exporter + hostname := "127.0.0.1" opts := []*Opts{ { - URI: fmt.Sprintf("mongodb://%s:%s", "127.0.0.1", tu.GetenvDefault("TEST_MONGODB_STANDALONE_PORT", "27017")), + URI: fmt.Sprintf("mongodb://%s", net.JoinHostPort(hostname, tu.GetenvDefault("TEST_MONGODB_STANDALONE_PORT", "27017"))), DirectConnect: true, ConnectTimeoutMS: 1000, }, { - URI: fmt.Sprintf("mongodb://%s:%s", "127.0.0.1", tu.GetenvDefault("TEST_MONGODB_S1_PRIMARY_PORT", "17001")), + URI: fmt.Sprintf("mongodb://%s", net.JoinHostPort(hostname, tu.GetenvDefault("TEST_MONGODB_S1_PRIMARY_PORT", "17001"))), DirectConnect: true, ConnectTimeoutMS: 1000, }, { - URI: fmt.Sprintf("mongodb://%s:%s", "127.0.0.1", tu.GetenvDefault("TEST_MONGODB_S2_PRIMARY_PORT", "17004")), + URI: fmt.Sprintf("mongodb://%s", net.JoinHostPort(hostname, tu.GetenvDefault("TEST_MONGODB_S2_PRIMARY_PORT", "17004"))), DirectConnect: true, ConnectTimeoutMS: 1000, }, { - URI: fmt.Sprintf("mongodb://%s:%s", "127.0.0.1", "12345"), + URI: fmt.Sprintf("mongodb://%s", net.JoinHostPort(hostname, "12345")), DirectConnect: true, ConnectTimeoutMS: 1000, }, } - for _, opt := range opts { - exporters = append(exporters, New(opt)) + exporters := make([]*Exporter, len(opts)) + + for i, opt := range opts { + exporters[i] = New(opt) } log := logrus.New() - ServerMap = buildServerMap(exporters, log) + buildServerMap(exporters, log) expected := []string{ "mongodb_up 1\n", diff --git a/exporter/server.go b/exporter/server.go index b04818246..f8f4ad967 100644 --- a/exporter/server.go +++ b/exporter/server.go @@ -5,14 +5,17 @@ import ( "net/url" "os" "strings" + "time" "github.com/prometheus/common/promlog" "github.com/prometheus/exporter-toolkit/web" "github.com/sirupsen/logrus" ) -var ServerMap map[string]http.Handler +// ServerMap stores http handlers for each host +var serverMap map[string]http.Handler +// ServerOpts is the options for the main http handler type ServerOpts struct { Path string MultiTargetPath string @@ -20,6 +23,7 @@ type ServerOpts struct { TLSConfigPath string } +// Runs the main web-server func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *logrus.Logger) { mux := http.DefaultServeMux @@ -27,23 +31,27 @@ func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *logrus.Logger) { panic("No exporters were builded. You must specify --mongodb.uri command argument or MONGODB_URI environment variable") } - ServerMap = buildServerMap(exporters, log) + buildServerMap(exporters, log) defaultExporter := exporters[0] mux.Handle(opts.Path, defaultExporter.Handler()) mux.HandleFunc(opts.MultiTargetPath, multiTargetHandler) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(` + _, err := w.Write([]byte(` MongoDB Exporter

MongoDB Exporter

Metrics

`)) + if err != nil { + log.Errorf("error writing response: %v", err) + } }) server := &http.Server{ - Handler: mux, + ReadHeaderTimeout: 2 * time.Second, + Handler: mux, } flags := &web.FlagConfig{ WebListenAddresses: &[]string{opts.WebListenAddress}, @@ -62,7 +70,7 @@ func multiTargetHandler(w http.ResponseWriter, r *http.Request) { targetHost = "mongodb://" + targetHost } if uri, err := url.Parse(targetHost); err == nil { - if e, ok := ServerMap[uri.Host]; ok { + if e, ok := serverMap[uri.Host]; ok { e.ServeHTTP(w, r) return } @@ -72,7 +80,7 @@ func multiTargetHandler(w http.ResponseWriter, r *http.Request) { } func buildServerMap(exporters []*Exporter, log *logrus.Logger) map[string]http.Handler { - serverMap := make(map[string]http.Handler, len(exporters)) + serverMap = make(map[string]http.Handler, len(exporters)) for _, e := range exporters { if url, err := url.Parse(e.opts.URI); err == nil { serverMap[url.Host] = e.Handler() diff --git a/main.go b/main.go index 228b1f3f8..ce7c29c2c 100644 --- a/main.go +++ b/main.go @@ -144,11 +144,12 @@ func buildExporter(opts GlobalFlags, uri string, log *logrus.Logger) *exporter.E } func buildServers(opts GlobalFlags, log *logrus.Logger) []*exporter.Exporter { - var servers []*exporter.Exporter - if len(opts.URI) == 1 { opts.URI = strings.Split(opts.URI[0], " ") } + + servers := make([]*exporter.Exporter, len(opts.URI)) + for serverIdx := range opts.URI { URI := opts.URI[serverIdx] @@ -157,7 +158,7 @@ func buildServers(opts GlobalFlags, log *logrus.Logger) []*exporter.Exporter { URI = "mongodb://" + URI } - servers = append(servers, buildExporter(opts, URI, log)) + servers[serverIdx] = buildExporter(opts, URI, log) } return servers From 4dc883abf499df684f682da65280388da1c466d3 Mon Sep 17 00:00:00 2001 From: adnull Date: Sun, 24 Sep 2023 12:30:22 +0300 Subject: [PATCH 14/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d89841f8..9ba57d7ef 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ mongodb_exporter_linux_amd64/mongodb_exporter --mongodb.uri=mongodb://127.0.0.1: ``` #### Multi-target support -You can run the exporter specifying multiple URIs, devided by a comma in --mongodb.uri option or MONGODB_URI environment variable to gain the ability to monitor multipleemongob instances with the a single mongodb_exporter instance. +You can run the exporter specifying multiple URIs, devided by a comma in --mongodb.uri option or MONGODB_URI environment variable in order to monitor multiple mongob instances with the a single mongodb_exporter instance. ```sh --mongodb.uri=mongodb://user:pass@127.0.0.1:27017/admin,mongodb://user2:pass2@127.0.0.1:27018/admin ``` From b00d3cdd6668b5ed9703626961603dbf7980f3f7 Mon Sep 17 00:00:00 2001 From: adnull Date: Sun, 24 Sep 2023 12:31:01 +0300 Subject: [PATCH 15/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ba57d7ef..6fbd05511 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ mongodb_exporter_linux_amd64/mongodb_exporter --mongodb.uri=mongodb://127.0.0.1: ``` #### Multi-target support -You can run the exporter specifying multiple URIs, devided by a comma in --mongodb.uri option or MONGODB_URI environment variable in order to monitor multiple mongob instances with the a single mongodb_exporter instance. +You can run the exporter specifying multiple URIs, devided by a comma in --mongodb.uri option or MONGODB_URI environment variable in order to monitor multiple mongodb instances with the a single mongodb_exporter instance. ```sh --mongodb.uri=mongodb://user:pass@127.0.0.1:27017/admin,mongodb://user2:pass2@127.0.0.1:27018/admin ``` From 44ec28327c98c4a46466c59418bb3f3fb96391ad Mon Sep 17 00:00:00 2001 From: ad Date: Wed, 27 Sep 2023 19:09:01 +0300 Subject: [PATCH 16/20] updated license --- exporter/multi_target_test.go | 19 +++++++++---------- exporter/server.go | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/exporter/multi_target_test.go b/exporter/multi_target_test.go index 612d68d6e..70acebbfa 100644 --- a/exporter/multi_target_test.go +++ b/exporter/multi_target_test.go @@ -1,18 +1,17 @@ // mongodb_exporter // Copyright (C) 2017 Percona LLC // -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// 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 // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. +// http://www.apache.org/licenses/LICENSE-2.0 // -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +// 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 diff --git a/exporter/server.go b/exporter/server.go index f8f4ad967..d9e2fe29c 100644 --- a/exporter/server.go +++ b/exporter/server.go @@ -1,3 +1,18 @@ +// 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 ( From 88f5c8982e9597bd661298f99c69a2009bb49b7d Mon Sep 17 00:00:00 2001 From: adnull Date: Sun, 8 Oct 2023 17:48:59 +0300 Subject: [PATCH 17/20] Update exporter/server.go Co-authored-by: Nurlan Moldomurov --- exporter/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/server.go b/exporter/server.go index d9e2fe29c..0ce8e28ec 100644 --- a/exporter/server.go +++ b/exporter/server.go @@ -43,7 +43,7 @@ func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *logrus.Logger) { mux := http.DefaultServeMux if len(exporters) == 0 { - panic("No exporters were builded. You must specify --mongodb.uri command argument or MONGODB_URI environment variable") + panic("No exporters were built. You must specify --mongodb.uri command argument or MONGODB_URI environment variable") } buildServerMap(exporters, log) From c341b2abda720db60b3200200ad6c242d7e20071 Mon Sep 17 00:00:00 2001 From: ad Date: Sun, 8 Oct 2023 18:17:32 +0300 Subject: [PATCH 18/20] fixed according to review --- exporter/exporter.go | 6 ------ main.go | 9 +++++---- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/exporter/exporter.go b/exporter/exporter.go index c36c38867..ce11f0667 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -371,12 +371,6 @@ func connect(ctx context.Context, opts *Opts) (*mongo.Client, error) { clientOpts.SetServerSelectionTimeout(connectTimeout) } - if clientOpts.ConnectTimeout == nil { - connectTimeout := time.Duration(opts.ConnectTimeoutMS) * time.Millisecond - clientOpts.SetConnectTimeout(connectTimeout) - clientOpts.SetServerSelectionTimeout(connectTimeout) - } - client, err := mongo.Connect(ctx, clientOpts) if err != nil { return nil, fmt.Errorf("invalid MongoDB options: %w", err) diff --git a/main.go b/main.go index ab11e46d1..bbab1f2d3 100644 --- a/main.go +++ b/main.go @@ -72,7 +72,7 @@ type GlobalFlags struct { func main() { var opts GlobalFlags - _ = kong.Parse(&opts, + ctx := kong.Parse(&opts, kong.Name("mongodb_exporter"), kong.Description("MongoDB Prometheus exporter"), kong.UsageOnError(), @@ -108,6 +108,10 @@ func main() { opts.WebTelemetryPath = "/" } + if len(opts.URI) == 0 { + ctx.Fatalf("No MongoDB hosts were specified. You must specify the host(s) with the --mongodb.uri command argument or the MONGODB_URI environment variable") + } + serverOpts := &exporter.ServerOpts{ Path: opts.WebTelemetryPath, MultiTargetPath: "/scrape", @@ -155,9 +159,6 @@ func buildExporter(opts GlobalFlags, uri string, log *logrus.Logger) *exporter.E } func buildServers(opts GlobalFlags, log *logrus.Logger) []*exporter.Exporter { - if len(opts.URI) == 1 { - opts.URI = strings.Split(opts.URI[0], " ") - } servers := make([]*exporter.Exporter, len(opts.URI)) From 8dc058e1e063037c4594a595ecdb95f31a7963e3 Mon Sep 17 00:00:00 2001 From: ad Date: Tue, 10 Oct 2023 12:42:23 +0300 Subject: [PATCH 19/20] formatted the code --- main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main.go b/main.go index bbab1f2d3..62c214db4 100644 --- a/main.go +++ b/main.go @@ -159,7 +159,6 @@ func buildExporter(opts GlobalFlags, uri string, log *logrus.Logger) *exporter.E } func buildServers(opts GlobalFlags, log *logrus.Logger) []*exporter.Exporter { - servers := make([]*exporter.Exporter, len(opts.URI)) for serverIdx := range opts.URI { From 9573d8088f7ab04fd6ade4ffa3b93e246accc019 Mon Sep 17 00:00:00 2001 From: ad Date: Tue, 10 Oct 2023 16:08:28 +0300 Subject: [PATCH 20/20] minor changes according to the linters --- exporter/multi_target_test.go | 5 ++--- exporter/server.go | 40 +++++++++++++++++++---------------- internal/tu/testutils.go | 2 ++ main.go | 1 + 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/exporter/multi_target_test.go b/exporter/multi_target_test.go index 70acebbfa..f689ce7c7 100644 --- a/exporter/multi_target_test.go +++ b/exporter/multi_target_test.go @@ -18,7 +18,6 @@ package exporter import ( "fmt" "net" - "net/http" "testing" "github.com/sirupsen/logrus" @@ -57,7 +56,7 @@ func TestMultiTarget(t *testing.T) { exporters[i] = New(opt) } log := logrus.New() - buildServerMap(exporters, log) + serverMap := buildServerMap(exporters, log) expected := []string{ "mongodb_up 1\n", @@ -68,6 +67,6 @@ func TestMultiTarget(t *testing.T) { // Test all targets for sn, opt := range opts { - assert.HTTPBodyContains(t, http.HandlerFunc(multiTargetHandler), "GET", fmt.Sprintf("?target=%s", opt.URI), nil, expected[sn]) + assert.HTTPBodyContains(t, multiTargetHandler(serverMap), "GET", fmt.Sprintf("?target=%s", opt.URI), nil, expected[sn]) } } diff --git a/exporter/server.go b/exporter/server.go index 0ce8e28ec..6788acb31 100644 --- a/exporter/server.go +++ b/exporter/server.go @@ -28,7 +28,7 @@ import ( ) // ServerMap stores http handlers for each host -var serverMap map[string]http.Handler +type ServerMap map[string]http.Handler // ServerOpts is the options for the main http handler type ServerOpts struct { @@ -46,11 +46,12 @@ func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *logrus.Logger) { panic("No exporters were built. You must specify --mongodb.uri command argument or MONGODB_URI environment variable") } - buildServerMap(exporters, log) + serverMap := buildServerMap(exporters, log) defaultExporter := exporters[0] mux.Handle(opts.Path, defaultExporter.Handler()) - mux.HandleFunc(opts.MultiTargetPath, multiTargetHandler) + mux.HandleFunc(opts.MultiTargetPath, multiTargetHandler(serverMap)) + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { _, err := w.Write([]byte(` MongoDB Exporter @@ -78,30 +79,33 @@ func RunWebServer(opts *ServerOpts, exporters []*Exporter, log *logrus.Logger) { } } -func multiTargetHandler(w http.ResponseWriter, r *http.Request) { - targetHost := r.URL.Query().Get("target") - if targetHost != "" { - if !strings.HasPrefix(targetHost, "mongodb://") { - targetHost = "mongodb://" + targetHost - } - if uri, err := url.Parse(targetHost); err == nil { - if e, ok := serverMap[uri.Host]; ok { - e.ServeHTTP(w, r) - return +func multiTargetHandler(serverMap ServerMap) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + targetHost := r.URL.Query().Get("target") + if targetHost != "" { + if !strings.HasPrefix(targetHost, "mongodb://") { + targetHost = "mongodb://" + targetHost + } + if uri, err := url.Parse(targetHost); err == nil { + if e, ok := serverMap[uri.Host]; ok { + e.ServeHTTP(w, r) + return + } } } + http.Error(w, "Unable to find target", http.StatusNotFound) } - http.Error(w, "Unable to find target", http.StatusNotFound) } -func buildServerMap(exporters []*Exporter, log *logrus.Logger) map[string]http.Handler { - serverMap = make(map[string]http.Handler, len(exporters)) +func buildServerMap(exporters []*Exporter, log *logrus.Logger) ServerMap { + servers := make(ServerMap, len(exporters)) for _, e := range exporters { if url, err := url.Parse(e.opts.URI); err == nil { - serverMap[url.Host] = e.Handler() + servers[url.Host] = e.Handler() } else { log.Errorf("Unable to parse addr %s as url: %s", e.opts.URI, err) } } - return serverMap + + return servers } diff --git a/internal/tu/testutils.go b/internal/tu/testutils.go index ce138ab3f..a93ccdfe1 100644 --- a/internal/tu/testutils.go +++ b/internal/tu/testutils.go @@ -67,6 +67,7 @@ func GetenvDefault(key, defaultValue string) string { func DefaultTestClient(ctx context.Context, t *testing.T) *mongo.Client { port, err := PortForContainer("mongo-1-1") require.NoError(t, err) + return TestClient(ctx, port, t) } @@ -103,6 +104,7 @@ func GetImageNameForDefault() (string, string, error) { break } } + return imageBaseName, version, nil } diff --git a/main.go b/main.go index 62c214db4..83948ff27 100644 --- a/main.go +++ b/main.go @@ -187,5 +187,6 @@ func buildURI(uri string, user string, password string) string { if !strings.HasPrefix(uri, "mongodb") { uri = "mongodb://" + uri } + return uri }