From 1fa124ed59d1f0b2b1b7e50a84e9b0e0835fa9d9 Mon Sep 17 00:00:00 2001 From: Richa Talwar <102972658+ritalwar@users.noreply.github.com> Date: Tue, 6 Feb 2024 19:41:01 +0530 Subject: [PATCH] [8.12](backport #37688) Update getOpTimestamp in replstatus to fix sort and temp files generation issue (#37855) * metricbeat/module/mongodb/replstatus: Update `getOpTimestamp` in `replstatus` to fix sort and temp files generation issue (#37688) --- CHANGELOG.next.asciidoc | 1 + metricbeat/module/mongodb/replstatus/info.go | 47 ++++++++++---------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index bc38d8e5b352..755ba1aff00b 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -164,6 +164,7 @@ you can achieve this by overwriting the value using an `add_fields` processor. { - Add GCP CloudSQL metadata {pull}33066[33066] - Add GCP Carbon Footprint metricbeat data {pull}34820[34820] - Add event loop utilization metric to Kibana module {pull}35020[35020] +- Update `getOpTimestamp` in `replstatus` to fix sort and temp files generation issue in mongodb. {pull}37688[37688] *Osquerybeat* diff --git a/metricbeat/module/mongodb/replstatus/info.go b/metricbeat/module/mongodb/replstatus/info.go index 037aeda09502..a444fa03b1ff 100644 --- a/metricbeat/module/mongodb/replstatus/info.go +++ b/metricbeat/module/mongodb/replstatus/info.go @@ -21,11 +21,10 @@ import ( "context" "errors" "fmt" + "time" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" ) type oplogInfo struct { @@ -71,14 +70,9 @@ func getReplicationInfo(client *mongo.Client) (*oplogInfo, error) { } // get first and last items in the oplog - firstTs, err := getOpTimestamp(collection, "$natural") + firstTs, lastTs, err := getOpTimestamp(collection) if err != nil { - return nil, fmt.Errorf("could not get first operation timestamp in op log: %w", err) - } - - lastTs, err := getOpTimestamp(collection, "-$natural") - if err != nil { - return nil, fmt.Errorf("could not get last operation timestamp in op log: %w", err) + return nil, fmt.Errorf("could not get operation timestamp in op log: %w", err) } diff := lastTs - firstTs @@ -92,28 +86,35 @@ func getReplicationInfo(client *mongo.Client) (*oplogInfo, error) { }, nil } -func getOpTimestamp(collection *mongo.Collection, sort string) (uint32, error) { - opt := options.Find().SetSort(bson.D{{Key: sort, Value: 1}}) - cursor, err := collection.Find(context.Background(), bson.D{}, opt) - if err != nil { - return 0, fmt.Errorf("could not get cursor on collection '%s': %w", collection.Name(), err) +func getOpTimestamp(collection *mongo.Collection) (uint32, uint32, error) { + + // Find both first and last timestamps using $min and $max + pipeline := bson.A{ + bson.M{"$group": bson.M{"_id": 1, "minTS": bson.M{"$min": "$ts"}, "maxTS": bson.M{"$max": "$ts"}}}, } - if !cursor.Next(context.Background()) { - return 0, errors.New("objects not found in local.oplog.rs") + cursor, err := collection.Aggregate(context.Background(), pipeline) + if err != nil { + return 0, 0, fmt.Errorf("could not get operation timestamps in op log: %w", err) } + defer cursor.Close(context.Background()) - var opTime map[string]interface{} - if err = cursor.Decode(&opTime); err != nil { - return 0, fmt.Errorf("error decoding response: %w", err) + var result struct { + MinTS time.Time `bson:"minTS"` + MaxTS time.Time `bson:"maxTS"` } - ts, ok := opTime["ts"].(primitive.Timestamp) - if !ok { - return 0, errors.New("an expected timestamp was not found") + if !cursor.Next(context.Background()) { + return 0, 0, errors.New("no documents found in op log") } + if err := cursor.Decode(&result); err != nil { + return 0, 0, fmt.Errorf("error decoding response for timestamps: %w", err) + } + + minTS := uint32(result.MinTS.Unix()) + maxTS := uint32(result.MaxTS.Unix()) - return ts.T, nil + return minTS, maxTS, nil } func contains(s []string, x string) bool {