Skip to content

Commit be17763

Browse files
authored
Merge branch 'main' into replSetGetConfigCollector
2 parents 296e11b + 4f3568b commit be17763

File tree

8 files changed

+239
-0
lines changed

8 files changed

+239
-0
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Release 0.20.8
2+
Improvement PMM-7424: Add dbStats metric
3+
Improvement : Add support for compatible mode for dbStats metric to provide old metrics
4+
15
Release 0.20.7 released 2021-08-10
26

37
Improvement : Upgraded dependencies

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Currently, these metric sources are implemented:
4141
|\-\-disable.diagnosticdata|Disable collecting metrics from getDiagnosticData||
4242
|\-\-disable.replicasetstatus|Disable collecting metrics from replSetGetStatus||
4343
|\-\-disable.replicasetconfig|Disable collecting metrics from replSetGetConfig||
44+
|\-\-disable.dbstats|Disable collecting metrics from dbStats||
4445
|--version|Show version and exit|
4546

4647
### Build the exporter

exporter/dbstats_collector.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// mongodb_exporter
2+
// Copyright (C) 2017 Percona LLC
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
package exporter
18+
19+
import (
20+
"context"
21+
22+
"github.com/prometheus/client_golang/prometheus"
23+
"github.com/sirupsen/logrus"
24+
"go.mongodb.org/mongo-driver/bson"
25+
"go.mongodb.org/mongo-driver/mongo"
26+
)
27+
28+
type dbstatsCollector struct {
29+
ctx context.Context
30+
client *mongo.Client
31+
compatibleMode bool
32+
logger *logrus.Logger
33+
topologyInfo labelsGetter
34+
}
35+
36+
func (d *dbstatsCollector) Describe(ch chan<- *prometheus.Desc) {
37+
prometheus.DescribeByCollect(d, ch)
38+
}
39+
40+
func (d *dbstatsCollector) Collect(ch chan<- prometheus.Metric) {
41+
// List all databases names
42+
dbNames, err := d.client.ListDatabaseNames(d.ctx, bson.M{})
43+
if err != nil {
44+
d.logger.Errorf("Failed to get database names: %s", err)
45+
return
46+
}
47+
d.logger.Debugf("getting stats for databases: %v", dbNames)
48+
for _, db := range dbNames {
49+
var dbStats bson.M
50+
cmd := bson.D{{Key: "dbStats", Value: 1}, {Key: "scale", Value: 1}}
51+
r := d.client.Database(db).RunCommand(d.ctx, cmd)
52+
err := r.Decode(&dbStats)
53+
if err != nil {
54+
d.logger.Errorf("Failed to get $dbstats for database %s: %s", db, err)
55+
continue
56+
}
57+
58+
d.logger.Debugf("$dbStats metrics for %s", db)
59+
debugResult(d.logger, dbStats)
60+
61+
prefix := "dbstats"
62+
63+
labels := d.topologyInfo.baseLabels()
64+
65+
// Since all dbstats will have the same fields, we need to use a label
66+
// to differentiate metrics between different databases.
67+
labels["database"] = db
68+
69+
for _, metric := range makeMetrics(prefix, dbStats, labels, d.compatibleMode) {
70+
ch <- metric
71+
}
72+
}
73+
}
74+
75+
var _ prometheus.Collector = (*dbstatsCollector)(nil)

exporter/dbstats_collector_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// mongodb_exporter
2+
// Copyright (C) 2017 Percona LLC
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
package exporter
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"sort"
23+
"testing"
24+
"time"
25+
26+
"github.com/percona/exporter_shared/helpers"
27+
"github.com/sirupsen/logrus"
28+
"github.com/stretchr/testify/assert"
29+
"go.mongodb.org/mongo-driver/bson"
30+
31+
"github.com/percona/mongodb_exporter/internal/tu"
32+
)
33+
34+
func TestDBStatsCollector(t *testing.T) {
35+
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
36+
defer cancel()
37+
38+
client := tu.DefaultTestClient(ctx, t)
39+
40+
database := client.Database("testdb")
41+
database.Drop(ctx) //nolint
42+
43+
defer func() {
44+
err := database.Drop(ctx)
45+
assert.NoError(t, err)
46+
}()
47+
48+
for i := 0; i < 3; i++ {
49+
coll := fmt.Sprintf("testcol_%02d", i)
50+
for j := 0; j < 10; j++ {
51+
_, err := database.Collection(coll).InsertOne(ctx, bson.M{"f1": j, "f2": "2"})
52+
assert.NoError(t, err)
53+
}
54+
}
55+
56+
ti := labelsGetterMock{}
57+
58+
c := &dbstatsCollector{
59+
client: client,
60+
logger: logrus.New(),
61+
topologyInfo: ti,
62+
}
63+
64+
expected := []string{
65+
"# HELP mongodb_dbstats_collections dbstats.",
66+
"# TYPE mongodb_dbstats_collections untyped",
67+
"mongodb_dbstats_collections{database=\"testdb\"} 3",
68+
"# HELP mongodb_dbstats_dataSize dbstats.",
69+
"# TYPE mongodb_dbstats_dataSize untyped",
70+
"mongodb_dbstats_dataSize{database=\"testdb\"} 1200",
71+
"# HELP mongodb_dbstats_indexSize dbstats.",
72+
"# TYPE mongodb_dbstats_indexSize untyped",
73+
"mongodb_dbstats_indexSize{database=\"testdb\"} 12288",
74+
"# HELP mongodb_dbstats_indexes dbstats.",
75+
"# TYPE mongodb_dbstats_indexes untyped",
76+
"mongodb_dbstats_indexes{database=\"testdb\"} 3",
77+
"# HELP mongodb_dbstats_objects dbstats.",
78+
"# TYPE mongodb_dbstats_objects untyped",
79+
"mongodb_dbstats_objects{database=\"testdb\"} 30",
80+
}
81+
82+
metrics := helpers.CollectMetrics(c)
83+
actualMetrics := helpers.ReadMetrics(metrics)
84+
filters := []string{
85+
"mongodb_dbstats_collections",
86+
"mongodb_dbstats_dataSize",
87+
"mongodb_dbstats_indexSize",
88+
"mongodb_dbstats_indexes",
89+
"mongodb_dbstats_objects",
90+
}
91+
labels := map[string]string{
92+
"database": "testdb",
93+
}
94+
actualMetrics = filterMetricsWithLabels(actualMetrics,
95+
filters,
96+
labels)
97+
actualLines := helpers.Format(helpers.WriteMetrics(actualMetrics))
98+
sort.Strings(actualLines)
99+
sort.Strings(expected)
100+
assert.Equal(t, expected, actualLines)
101+
}

exporter/exporter.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type Opts struct {
5555
DisableDiagnosticData bool
5656
DisableReplicasetStatus bool
5757
DisableReplicasetConfig bool
58+
DisableDBStats bool
5859
}
5960

6061
var (
@@ -148,6 +149,17 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
148149
registry.MustRegister(&ddc)
149150
}
150151

152+
if !e.opts.DisableDBStats {
153+
cc := dbstatsCollector{
154+
ctx: ctx,
155+
client: client,
156+
compatibleMode: e.opts.CompatibleMode,
157+
logger: e.opts.Logger,
158+
topologyInfo: topologyInfo,
159+
}
160+
registry.MustRegister(&cc)
161+
}
162+
151163
// replSetGetStatus is not supported through mongos
152164
if !e.opts.DisableReplicasetStatus && nodeType != typeMongos {
153165
rsgsc := replSetGetStatusCollector{

exporter/utils_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,27 @@ func getMetricNames(lines []string) map[string]bool {
3535

3636
return names
3737
}
38+
39+
func filterMetricsWithLabels(metrics []*helpers.Metric, filters []string, labels map[string]string) []*helpers.Metric {
40+
res := make([]*helpers.Metric, 0, len(metrics))
41+
for _, m := range metrics {
42+
for _, filterName := range filters {
43+
if m.Name == filterName {
44+
validMetric := true
45+
for labelKey, labelValue := range labels {
46+
if m.Labels[labelKey] != labelValue {
47+
validMetric = false
48+
49+
break
50+
}
51+
}
52+
if validMetric {
53+
res = append(res, m)
54+
}
55+
56+
break
57+
}
58+
}
59+
}
60+
return res
61+
}

exporter/v1_compatibility.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,26 @@ func conversions() []conversion {
592592
oldName: "mongodb_ss_wt_cache_maximum_bytes_configured",
593593
newName: "mongodb_mongod_wiredtiger_cache_max_bytes",
594594
},
595+
{
596+
oldName: "mongodb_mongod_db_collections_total",
597+
newName: "mongodb_dbstats_collections",
598+
},
599+
{
600+
oldName: "mongodb_mongod_db_data_size_bytes",
601+
newName: "mongodb_dbstats_dataSize",
602+
},
603+
{
604+
oldName: "mongodb_mongod_db_index_size_bytes",
605+
newName: "mongodb_dbstats_indexSize",
606+
},
607+
{
608+
oldName: "mongodb_mongod_db_indexes_total",
609+
newName: "mongodb_dbstats_indexes",
610+
},
611+
{
612+
oldName: "mongodb_mongod_db_objects_total",
613+
newName: "mongodb_dbstats_objects",
614+
},
595615
}
596616
}
597617

main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ type GlobalFlags struct {
4848
DisableDiagnosticData bool `name:"disable.diagnosticdata" help:"Disable collecting metrics from getDiagnosticData"`
4949
DisableReplicasetStatus bool `name:"disable.replicasetstatus" help:"Disable collecting metrics from replSetGetStatus"`
5050
DisableReplicasetConfig bool `name:"disable.replicasetconfig" help:"Disable collecting metrics from replSetGetConfig"`
51+
DisableDBStats bool `name:"disable.dbstats" help:"Disable collecting metrics from dbStats"`
5152

5253
DiscoveringMode bool `name:"discovering-mode" help:"Enable autodiscover collections"`
5354
CompatibleMode bool `name:"compatible-mode" help:"Enable old mongodb-exporter compatible metrics"`
@@ -119,6 +120,7 @@ func buildExporter(opts GlobalFlags) (*exporter.Exporter, error) {
119120
DisableReplicasetStatus: opts.DisableReplicasetStatus,
120121
DisableReplicasetConfig: opts.DisableReplicasetConfig,
121122
DirectConnect: opts.DirectConnect,
123+
DisableDBStats: opts.DisableDBStats,
122124
}
123125

124126
e, err := exporter.New(exporterOpts)

0 commit comments

Comments
 (0)