Skip to content

Commit

Permalink
PMM-13141 Added feature compatibility version collector (#863)
Browse files Browse the repository at this point in the history
* PMM-13141 Added feature compatibility version collector

* PMM-13141 Fixed testing mongo version

* PMM-13141 Ran format

* PMM-13141 Fix for linters

* PMM-13141 Fixed tests for different mdb versions

* PMM-13141 Fix for linters

* PMM-13141 Trigger build

* PMM-13141 Fix for linters

* PMM-13141 Trigger build

* PMM-13141 Removed scrape interval.

* PMM-13141 Removed last_scrape label.

* PMM-13141 Fix linters.

* PMM-13141 fix test.

* PMM-13141 fix test.

* PMM-13141 fix test.

* PMM-13141 fix test.

* PMM-13141 fix test.

* PMM-13141 fix test.

* PMM-13141 fix test.

---------

Co-authored-by: Jiří Čtvrtka <[email protected]>
Co-authored-by: Nurlan Moldomurov <[email protected]>
  • Loading branch information
3 people authored Sep 13, 2024
1 parent 88ce83d commit 23502f1
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 64 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ REPO ?= percona/$(NAME)
GORELEASER_FLAGS ?=
UID ?= $(shell id -u)

export TEST_MONGODB_IMAGE?=mongo:4.2
export TEST_MONGODB_IMAGE?=mongo:4.4
export TEST_MONGODB_ADMIN_USERNAME?=
export TEST_MONGODB_ADMIN_PASSWORD?=
export TEST_MONGODB_USERNAME?=
Expand Down
26 changes: 13 additions & 13 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
services:
mongo-1-1:
container_name: "mongo-1-1"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
ports:
- "${TEST_MONGODB_S1_PRIMARY_PORT:-17001}:27017"
command: mongod --replSet rs1 --shardsvr --port 27017 --oplogSize 16 --bind_ip 0.0.0.0
Expand All @@ -14,7 +14,7 @@ services:

mongo-1-2:
container_name: "mongo-1-2"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
ports:
- "${TEST_MONGODB_S1_SECONDARY1_PORT:-17002}:27017"
command: mongod --replSet rs1 --shardsvr --port 27017 --oplogSize 16 --bind_ip 0.0.0.0
Expand All @@ -23,7 +23,7 @@ services:

mongo-1-3:
container_name: "mongo-1-3"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
ports:
- "${TEST_MONGODB_S1_SECONDARY2_PORT:-17003}:27017"
command: mongod --replSet rs1 --shardsvr --port 27017 --oplogSize 16 --bind_ip 0.0.0.0
Expand All @@ -32,7 +32,7 @@ services:

mongo-1-arbiter:
container_name: "mongo-1-arbiter"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
ports:
- "${TEST_MONGODB_S1_ARBITER:-17011}:27017"
command: mongod --replSet rs1 --shardsvr --port 27017 --oplogSize 16
Expand All @@ -41,7 +41,7 @@ services:

mongo-rs1-setup:
container_name: "mongo-rs1-setup"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
depends_on:
- "mongo-1-1"
- "mongo-1-2"
Expand Down Expand Up @@ -150,7 +150,7 @@ services:

mongo-rs2-setup:
container_name: "mongo-rs2-setup"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
depends_on:
- "mongo-2-1"
- "mongo-2-2"
Expand All @@ -174,7 +174,7 @@ services:
# Config servers
mongo-cnf-2:
container_name: "mongo-cnf-2"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
ports:
- "${TEST_MONGODB_CONFIGSVR1_PORT:-17007}:27017"
command: mongod --dbpath /data/db --replSet cnf-serv --configsvr --port 27017 --oplogSize 16
Expand All @@ -183,7 +183,7 @@ services:

mongo-cnf-3:
container_name: "mongo-cnf-3"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
ports:
- "${TEST_MONGODB_CONFIGSVR2_PORT:-17008}:27017"
command: mongod --dbpath /data/db --replSet cnf-serv --configsvr --port 27017 --oplogSize 16
Expand All @@ -192,7 +192,7 @@ services:

mongo-cnf-1:
container_name: "mongo-cnf-1"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
ports:
- "${TEST_MONGODB_CONFIGSVR3_PORT:-17009}:27017"
command: mongod --dbpath /data/db --replSet cnf-serv --configsvr --port 27017 --oplogSize 16
Expand All @@ -204,7 +204,7 @@ services:

mongo-cnf-setup:
container_name: "mongo-cnf-setup"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
depends_on:
- "mongo-cnf-1"
- "mongo-cnf-2"
Expand All @@ -224,7 +224,7 @@ services:

mongos:
container_name: "mongos"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
ports:
- "${TEST_MONGODB_MONGOS_PORT:-17000}:27017"
networks:
Expand All @@ -240,7 +240,7 @@ services:

mongo-shard-setup:
container_name: "mongo-shard-setup"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
depends_on:
- "mongos"
networks:
Expand Down Expand Up @@ -270,7 +270,7 @@ services:

standalone:
container_name: "standalone"
image: ${TEST_MONGODB_IMAGE:-mongo:4.2}
image: ${TEST_MONGODB_IMAGE:-mongo:4.4}
ports:
- "${TEST_MONGODB_STANDALONE_PORT:-27017}:27017"
command: mongod --port 27017 --oplogSize 16
Expand Down
10 changes: 10 additions & 0 deletions exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type Opts struct {
EnableCollStats bool
EnableProfile bool
EnableShards bool
EnableFCV bool // Feature Compatibility Version.

EnableOverrideDescendingIndex bool

Expand Down Expand Up @@ -164,6 +165,7 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
e.opts.EnableCurrentopMetrics = true
e.opts.EnableProfile = true
e.opts.EnableShards = true
e.opts.EnableFCV = true
e.opts.EnablePBMMetrics = true
}

Expand All @@ -178,6 +180,7 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
e.opts.EnableCurrentopMetrics = false
e.opts.EnableProfile = false
e.opts.EnableShards = false
e.opts.EnableFCV = false
e.opts.EnablePBMMetrics = false
}

Expand Down Expand Up @@ -239,6 +242,11 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
registry.MustRegister(sc)
}

if e.opts.EnableFCV && nodeType != typeMongos {
fcvc := newFeatureCompatibilityCollector(ctx, client, e.opts.Logger)
registry.MustRegister(fcvc)
}

if e.opts.EnablePBMMetrics && requestOpts.EnablePBMMetrics {
pbmc := newPbmCollector(ctx, client, e.opts.URI, e.opts.Logger)
registry.MustRegister(pbmc)
Expand Down Expand Up @@ -320,6 +328,8 @@ func (e *Exporter) Handler() http.Handler {
requestOpts.EnableProfile = true
case "shards":
requestOpts.EnableShards = true
case "fcv":
requestOpts.EnableFCV = true
case "pbm":
requestOpts.EnablePBMMetrics = true
}
Expand Down
79 changes: 29 additions & 50 deletions exporter/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,34 +199,11 @@ 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)
nodeType, _ := getNodeType(ctx, client)
gc := newGeneralCollector(ctx, client, nodeType, 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 {
name string
URI string
clusterRole string
Want int
Expand All @@ -242,39 +219,41 @@ func TestMongoUpMetric(t *testing.T) {
}

for _, tc := range testCases {
exporterOpts := &Opts{
Logger: logrus.New(),
URI: tc.URI,
ConnectTimeoutMS: 200,
DirectConnect: true,
GlobalConnPool: false,
CollectAll: true,
}
t.Run(tc.clusterRole+"/"+tc.URI, func(t *testing.T) {
exporterOpts := &Opts{
Logger: logrus.New(),
URI: tc.URI,
ConnectTimeoutMS: 200,
DirectConnect: true,
GlobalConnPool: false,
CollectAll: true,
}

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)
}
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)
}

e := New(exporterOpts)
nodeType, _ := getNodeType(ctx, client)
gc := newGeneralCollector(ctx, client, nodeType, e.opts.Logger)
r := e.makeRegistry(ctx, client, new(labelsGetterMock), *e.opts)
e := New(exporterOpts)
nodeType, _ := getNodeType(ctx, client)
gc := newGeneralCollector(ctx, client, nodeType, e.opts.Logger)
r := e.makeRegistry(ctx, client, new(labelsGetterMock), *e.opts)

expected := strings.NewReader(fmt.Sprintf(`
expected := strings.NewReader(fmt.Sprintf(`
# HELP mongodb_up Whether MongoDB is up.
# TYPE mongodb_up gauge
mongodb_up {cluster_role="%s"} %s`, tc.clusterRole, strconv.Itoa(tc.Want)) + "\n")

filter := []string{
"mongodb_up",
}
err = testutil.CollectAndCompare(gc, expected, filter...)
assert.NoError(t, err, "mongodb_up metric should be %d", tc.Want)
filter := []string{
"mongodb_up",
}
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)
res := r.Unregister(gc)
assert.Equal(t, true, res)
})
}
}
80 changes: 80 additions & 0 deletions exporter/feature_compatibility_version_collector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// 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"
"fmt"
"strconv"

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

type featureCompatibilityCollector struct {
ctx context.Context
base *baseCollector
}

// newProfileCollector creates a collector for being processed queries.
func newFeatureCompatibilityCollector(ctx context.Context, client *mongo.Client, logger *logrus.Logger) *featureCompatibilityCollector {
return &featureCompatibilityCollector{
ctx: ctx,
base: newBaseCollector(client, logger.WithFields(logrus.Fields{"collector": "featureCompatibility"})),
}
}

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

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

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

cmd := bson.D{{Key: "getParameter", Value: 1}, {Key: "featureCompatibilityVersion", Value: 1}}
client := d.base.client
if client == nil {
return
}
res := client.Database("admin").RunCommand(d.ctx, cmd)

m := make(map[string]interface{})
if err := res.Decode(&m); err != nil {
d.base.logger.Errorf("Failed to decode featureCompatibilityVersion: %v", err)
ch <- prometheus.NewInvalidMetric(prometheus.NewInvalidDesc(err), err)
return
}

rawValue := walkTo(m, []string{"featureCompatibilityVersion", "version"})
if rawValue != nil {
versionString := fmt.Sprintf("%v", rawValue)
version, err := strconv.ParseFloat(versionString, 64)
if err != nil {
d.base.logger.Errorf("Failed to parse featureCompatibilityVersion: %v", err)
ch <- prometheus.NewInvalidMetric(prometheus.NewInvalidDesc(err), err)
return
}

d := prometheus.NewDesc("mongodb_fcv_feature_compatibility_version", "Feature compatibility version", []string{"version"}, map[string]string{})
ch <- prometheus.MustNewConstMetric(d, prometheus.GaugeValue, version, versionString)
}
}
Loading

0 comments on commit 23502f1

Please sign in to comment.