Skip to content

Commit

Permalink
metricbeat/module/mongodb: Improve logic
Browse files Browse the repository at this point in the history
  • Loading branch information
shmsr committed Jan 8, 2025
1 parent 283e70d commit bc4feb6
Showing 1 changed file with 39 additions and 4 deletions.
43 changes: 39 additions & 4 deletions metricbeat/module/mongodb/replstatus/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,29 @@ type CollSize struct {

const oplogCol = "oplog.rs"

// getReplicationInfo returns oplog info from local.oplog.rs
func getReplicationInfo(client *mongo.Client) (*oplogInfo, error) {
// get oplog.rs collection
// Get oplog collection info from local.oplog.rs (<db>.<collection>)
db := client.Database("local")

// Get oplog size using collStats - this is lightweight
var oplogSize CollSize
// NOTE(shmsr):
// https://www.mongodb.com/docs/manual/reference/command/collStats/#syntax
// "scale" field is ommitted here as it is by default 1, i.e., it return sizes in bytes.

Check failure on line 53 in metricbeat/module/mongodb/replstatus/info.go

View workflow job for this annotation

GitHub Actions / lint (windows)

`ommitted` is a misspelling of `omitted` (misspell)
//
// Also, note that collStats is deprecated since v6.2 but as we support older
// versions i.e., >= 5.0, let's keep it for now as this still works.
// TODO(shmsr): For newers versions, we can use db.collection.stats()
// https://www.mongodb.com/docs/manual/reference/method/db.collection.stats/#mongodb-method-db.collection.stats
// or use this: https://github.com/percona/mongodb_exporter/blob/95d1865e34940d0d610bb1fbff9745bc66ddbc73/exporter/collstats_collector.go#L100
res := db.RunCommand(context.Background(), bson.D{
{Key: "collStats", Value: oplogCol},
})
if err := res.Err(); err != nil {
return nil, fmt.Errorf("collStats command failed: %w", err)
}

// Get MaxSize and Size from collStats by using db.runCommand
var oplogSize CollSize
if err := res.Decode(&oplogSize); err != nil {
return nil, fmt.Errorf("decode error: %w", err)
}
Expand All @@ -76,8 +87,32 @@ func getReplicationInfo(client *mongo.Client) (*oplogInfo, error) {
return info, nil
}

// getOpTimestamp returns the first and last timestamp of the oplog collection.
func getOpTimestamp(collection *mongo.Collection) (uint32, uint32, error) {
// Use natural order for efficiency
// NOTE(shmsr):
//
// When you do db.getReplicationInfo() in monogo shell (mongosh), you can see
// {
// ...
// tFirst: 'Tue Jan 07 2025 22:33:28 GMT+0530 (India Standard Time)',
// tLast: 'Wed Jan 08 2025 11:45:07 GMT+0530 (India Standard Time)',
// now: 'Wed Jan 08 2025 11:45:14 GMT+0530 (India Standard Time)'
// }
// i.e., we get tFirst and tLast from oplog.rs which is the first and last
// timestamp of the oplog.
// Source from the same is here:
// https://github.com/mongodb/mongo/blob/20cbee37a0ee4d40b35d08b6a34ade81252f86a8/src/mongo/shell/db.js#L863
// This is how they calculate tFirst and tLast:
// https://github.com/mongodb/mongo/blob/20cbee37a0ee4d40b35d08b6a34ade81252f86a8/src/mongo/shell/db.js#L889
// So ideally, we will replicate the same logic here:
// var firstc = ol.find().sort({$natural: 1}).limit(1);
// var lastc = ol.find().sort({$natural: -1}).limit(1);
//
// oplog.rs is designed to scanned in natural ($natural) order. So, when
// querying without any sort, it will return the first entry in natural order.
// When we sort in reverse natural order (i.e., $natural: -1), it will return
// the last entry in natural order.

var firstDoc struct {
Timestamp time.Time `bson:"ts"`
}
Expand Down

0 comments on commit bc4feb6

Please sign in to comment.