Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replSetGetConfigCollector #295

Merged
merged 29 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
31dca05
replSetGetConfigCollector. it just works
hiroshi Jun 12, 2021
ff968d7
Use member_idx for host field to match with replStatus
hiroshi Jun 13, 2021
0837f71
Add --disable.replicasetconfig option flag
hiroshi Jun 13, 2021
3bab659
Merge branch 'main' into replSetGetConfigCollector
hiroshi Jun 22, 2021
03c4922
Merge branch 'main' into replSetGetConfigCollector
JiriCtvrtka Jul 26, 2021
c5ba8b6
Merge branch 'main' into replSetGetConfigCollector
denisok Jul 27, 2021
f38e30b
Merge branch 'main' into replSetGetConfigCollector
JiriCtvrtka Jul 28, 2021
296e11b
Merge branch 'main' into replSetGetConfigCollector
JiriCtvrtka Aug 25, 2021
be17763
Merge branch 'main' into replSetGetConfigCollector
hiroshi Sep 19, 2021
54ded8c
Use errors.As() instead of type assertion.
hiroshi Sep 20, 2021
22b9fe3
Add replset_config_collector_test.
hiroshi Sep 20, 2021
678e125
Revert "Use errors.As() instead of type assertion."
hiroshi Sep 20, 2021
bb9ecc8
nolint - errors.As seems to cause segfault.
hiroshi Sep 21, 2021
bd5ca57
Merge remote-tracking branch 'origin/main' into replSetGetConfigColle…
hiroshi Feb 24, 2023
529c27c
Merge branch 'main' into replSetGetConfigCollector
BupycHuk Nov 11, 2024
1b2fe08
Update exporter/replset_config_collector.go
BupycHuk Nov 11, 2024
dc4899c
Update exporter/replset_config_collector_test.go
BupycHuk Nov 11, 2024
22cf389
Update exporter/replset_config_collector.go
BupycHuk Nov 11, 2024
8d051b0
Update exporter/replset_config_collector_test.go
BupycHuk Nov 11, 2024
ec5c37a
Update exporter/replset_config_collector.go
BupycHuk Nov 11, 2024
f5b0c15
Update exporter/exporter.go
BupycHuk Nov 11, 2024
58da23b
Update exporter/exporter.go
BupycHuk Nov 11, 2024
75ecc85
Update exporter/replset_config_collector_test.go
BupycHuk Nov 11, 2024
6578e64
Update replset_config_collector.go
BupycHuk Nov 11, 2024
0857d3d
Update replset_config_collector_test.go
BupycHuk Nov 11, 2024
08d54d2
Update exporter/replset_config_collector_test.go
BupycHuk Nov 11, 2024
12469dd
Update exporter/replset_config_collector.go
BupycHuk Nov 11, 2024
d4c588d
Update replset_config_collector.go
BupycHuk Nov 11, 2024
36c5423
Merge branch 'main' into replSetGetConfigCollector
BupycHuk Nov 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Currently, these metric sources are implemented:
- $indexStats
- getDiagnosticData
- replSetGetStatus
- replSetGetConfig
- serverStatus

## Supported MongoDB versions
Expand Down
10 changes: 10 additions & 0 deletions exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type Opts struct {
EnableDBStatsFreeStorage bool
EnableDiagnosticData bool
EnableReplicasetStatus bool
EnableReplicasetConfig bool
EnableCurrentopMetrics bool
EnableTopMetrics bool
EnableIndexStats bool
Expand Down Expand Up @@ -163,6 +164,7 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
e.opts.EnableCollStats = true
e.opts.EnableTopMetrics = true
e.opts.EnableReplicasetStatus = true
e.opts.EnableReplicasetConfig = true
e.opts.EnableIndexStats = true
e.opts.EnableCurrentopMetrics = true
e.opts.EnableProfile = true
Expand Down Expand Up @@ -239,6 +241,12 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
registry.MustRegister(rsgsc)
}

// replSetGetStatus is not supported through mongos.
if e.opts.EnableReplicasetConfig && nodeType != typeMongos && requestOpts.EnableReplicasetConfig {
rsgsc := newReplicationSetConfigCollector(ctx, client, e.opts.Logger,
e.opts.CompatibleMode, topologyInfo)
registry.MustRegister(rsgsc)
}
if e.opts.EnableShards && nodeType == typeMongos && requestOpts.EnableShards {
sc := newShardsCollector(ctx, client, e.opts.Logger, e.opts.CompatibleMode)
registry.MustRegister(sc)
Expand Down Expand Up @@ -374,6 +382,8 @@ func GetRequestOpts(filters []string, defaultOpts *Opts) Opts {
requestOpts.EnableDiagnosticData = true
case "replicasetstatus":
requestOpts.EnableReplicasetStatus = true
case "replicasetconfig":
requestOpts.EnableReplicasetConfig = true
case "dbstats":
requestOpts.EnableDBStats = true
case "topmetrics":
Expand Down
3 changes: 3 additions & 0 deletions exporter/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ func processSlice(prefix, k string, v []interface{}, commonLabels map[string]str
if state, ok := s["stateStr"].(string); ok {
labels["member_state"] = state
}
if host, ok := s["host"].(string); ok {
labels["member_idx"] = host
}

metrics = append(metrics, makeMetrics(prefix+k, s, labels, compatibleMode)...)
}
Expand Down
99 changes: 99 additions & 0 deletions exporter/replset_config_collector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// 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 (
"context"

"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)

// const (
// replicationNotEnabled = 76
// replicationNotYetInitialized = 94
// )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we keeping this for purpose?

BupycHuk marked this conversation as resolved.
Show resolved Hide resolved
BupycHuk marked this conversation as resolved.
Show resolved Hide resolved

type replSetGetConfigCollector struct {
ctx context.Context
base *baseCollector

compatibleMode bool
topologyInfo labelsGetter
}

// newReplicationSetConfigCollector creates a collector for configuration of replication set.
func newReplicationSetConfigCollector(ctx context.Context, client *mongo.Client, logger *logrus.Logger, compatible bool, topology labelsGetter) *replSetGetConfigCollector {
return &replSetGetConfigCollector{
ctx: ctx,
base: newBaseCollector(client, logger.WithFields(logrus.Fields{"collector": "replset_config"})),

compatibleMode: compatible,
topologyInfo: topology,
}
}

func (d *replSetGetConfigCollector) Describe(ch chan<- *prometheus.Desc) {
d.base.Describe(d.ctx, ch, d.collect)
}

func (d *replSetGetConfigCollector) Collect(ch chan<- prometheus.Metric) {
d.base.Collect(ch)
}

func (d *replSetGetConfigCollector) collect(ch chan<- prometheus.Metric) {
defer measureCollectTime(ch, "mongodb", "replset_config")()

logger := d.base.logger
client := d.base.client

cmd := bson.D{{Key: "replSetGetConfig", Value: "1"}}
res := client.Database("admin").RunCommand(d.ctx, cmd)

var m bson.M

if err := res.Decode(&m); err != nil {
if e, ok := err.(mongo.CommandError); ok { //nolint // https://github.com/percona/mongodb_exporter/pull/295#issuecomment-922874632
if e.Code == replicationNotYetInitialized || e.Code == replicationNotEnabled {
return
}
}
logger.Errorf("cannot get replSetGetConfig: %s", err)

return
}

config, ok := m["config"].(bson.M)
if !ok {
err := errors.Wrapf(errUnexpectedDataType, "%T for data field", m["config"])
logger.Errorf("cannot decode getDiagnosticData: %s", err)

return
}
m = config

logger.Debug("replSetGetConfig result:")
debugResult(logger, m)
ademidoff marked this conversation as resolved.
Show resolved Hide resolved

for _, metric := range makeMetrics("rs_cfg", m, d.topologyInfo.baseLabels(), d.compatibleMode) {
ch <- metric
}
}

var _ prometheus.Collector = (*replSetGetConfigCollector)(nil)
72 changes: 72 additions & 0 deletions exporter/replset_config_collector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// 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 (
"context"
"strings"
"testing"
"time"

"github.com/prometheus/client_golang/prometheus/testutil"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"

"github.com/percona/mongodb_exporter/internal/tu"
)

func TestReplsetConfigCollector(t *testing.T) {

Check failure on line 31 in exporter/replset_config_collector_test.go

View workflow job for this annotation

GitHub Actions / Lint Check

Function TestReplsetConfigCollector missing the call to method parallel (paralleltest)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

client := tu.DefaultTestClient(ctx, t)

ti := labelsGetterMock{}

c := newReplicationSetConfigCollector(ctx, client, logrus.New(), false, ti)

// The last \n at the end of this string is important
expected := strings.NewReader(`
# HELP mongodb_rs_cfg_protocolVersion rs_cfg.
# TYPE mongodb_rs_cfg_protocolVersion untyped
mongodb_rs_cfg_protocolVersion 1` + "\n")
// Filter metrics for 2 reasons:
// 1. The result is huge
// 2. We need to check against know values. Don't use metrics that return counters like uptime
// or counters like the number of transactions because they won't return a known value to compare
filter := []string{
"mongodb_rs_cfg_protocolVersion",
}
err := testutil.CollectAndCompare(c, expected, filter...)
assert.NoError(t, err)
}

func TestReplsetConfigCollectorNoSharding(t *testing.T) {

Check failure on line 57 in exporter/replset_config_collector_test.go

View workflow job for this annotation

GitHub Actions / Lint Check

Function TestReplsetConfigCollectorNoSharding missing the call to method parallel (paralleltest)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

client := tu.TestClient(ctx, tu.MongoDBStandAlonePort, t)

ti := labelsGetterMock{}

c := newReplicationSetConfigCollector(ctx, client, logrus.New(), false, ti)

// Replication set metrics should not be generated for unsharded server
count := testutil.CollectAndCount(c)

metaMetricCount := 1
assert.Equal(t, metaMetricCount, count, "Mismatch in metric count for collector run on unsharded server")
}
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
EnableExporterMetrics bool `name:"collector.exporter-metrics" help:"Enable collecting metrics about the exporter itself (process_*, go_*)" negatable:"" default:"True"`
EnableDiagnosticData bool `name:"collector.diagnosticdata" help:"Enable collecting metrics from getDiagnosticData"`
EnableReplicasetStatus bool `name:"collector.replicasetstatus" help:"Enable collecting metrics from replSetGetStatus"`
EnableReplicasetConfig bool `name:"collector.replicasetconfig" help:"Enable collecting metrics from replSetGetConfig"`

Check failure on line 57 in main.go

View workflow job for this annotation

GitHub Actions / Lint Check

tag is not aligned, should be: help:"Enable collecting metrics from replSetGetConfig" name:"collector.replicasetconfig" (tagalign)
EnableDBStats bool `name:"collector.dbstats" help:"Enable collecting metrics from dbStats"`
EnableDBStatsFreeStorage bool `name:"collector.dbstatsfreestorage" help:"Enable collecting free space metrics from dbStats"`
EnableTopMetrics bool `name:"collector.topmetrics" help:"Enable collecting metrics from top admin command"`
Expand Down Expand Up @@ -166,6 +167,7 @@
DisableDefaultRegistry: !opts.EnableExporterMetrics,
EnableDiagnosticData: opts.EnableDiagnosticData,
EnableReplicasetStatus: opts.EnableReplicasetStatus,
EnableReplicasetConfig: opts.EnableReplicasetConfig,
EnableCurrentopMetrics: opts.EnableCurrentopMetrics,
EnableTopMetrics: opts.EnableTopMetrics,
EnableDBStats: opts.EnableDBStats,
Expand Down
1 change: 1 addition & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func TestBuildExporter(t *testing.T) {

EnableDiagnosticData: true,
EnableReplicasetStatus: true,
EnableReplicasetConfig: true,

CompatibleMode: true,
}
Expand Down