github.com/epsagon/epsagon-go@v1.39.0/wrappers/mongo/mongo.go (about) 1 package epsagonmongo 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/epsagon/epsagon-go/epsagon" 8 "github.com/epsagon/epsagon-go/tracer" 9 "go.mongodb.org/mongo-driver/mongo" 10 mongoOptions "go.mongodb.org/mongo-driver/mongo/options" 11 ) 12 13 // MongoCollectionWrapper is Epsagon's wrapper for mongo.Collection 14 type MongoCollectionWrapper struct { 15 collection *mongo.Collection 16 tracer tracer.Tracer 17 } 18 19 func WrapMongoCollection( 20 collection *mongo.Collection, ctx ...context.Context, 21 ) *MongoCollectionWrapper { 22 return &MongoCollectionWrapper{ 23 collection: collection, 24 tracer: epsagon.ExtractTracer(ctx), 25 } 26 } 27 28 func (coll *MongoCollectionWrapper) Name() string { 29 return coll.collection.Name() 30 } 31 32 func (coll *MongoCollectionWrapper) Database() *mongo.Database { 33 return coll.collection.Database() 34 } 35 36 func (coll *MongoCollectionWrapper) Clone(opts ...*mongoOptions.CollectionOptions) (interface{}, error) { 37 event := startMongoEvent("Clone", coll) 38 response, err := coll.collection.Clone( 39 opts..., 40 ) 41 if err != nil { 42 logOperationFailure(fmt.Sprint("Could not complete Clone"), err.Error()) 43 coll.tracer.AddExceptionTypeAndMessage( 44 "mongo-driver", 45 err.Error(), 46 ) 47 } 48 if event != nil { 49 completeMongoEvent(coll.tracer, event) 50 } 51 return response, err 52 } 53 54 func (coll *MongoCollectionWrapper) InsertOne( 55 ctx context.Context, document interface{}, opts ...*mongoOptions.InsertOneOptions, 56 ) (*mongo.InsertOneResult, error) { 57 event := startMongoEvent("InsertOne", coll) 58 fmt.Println("EVENT::::") 59 fmt.Println(event) 60 response, err := coll.collection.InsertOne( 61 ctx, 62 document, 63 opts..., 64 ) 65 66 if err != nil { 67 logOperationFailure(fmt.Sprint("Could not complete InsertOne"), err.Error()) 68 coll.tracer.AddExceptionTypeAndMessage( 69 "mongo-driver", 70 err.Error(), 71 ) 72 } 73 74 if event != nil { 75 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 76 marshalToMetadata(event.Resource.Metadata, "document", document, config) 77 marshalToMetadata(event.Resource.Metadata, "response", response, config) 78 } 79 completeMongoEvent(coll.tracer, event) 80 } 81 return response, err 82 } 83 84 func (coll *MongoCollectionWrapper) InsertMany( 85 ctx context.Context, documents []interface{}, opts ...*mongoOptions.InsertManyOptions, 86 ) (*mongo.InsertManyResult, error) { 87 event := startMongoEvent("InsertMany", coll) 88 response, err := coll.collection.InsertMany( 89 ctx, 90 documents, 91 opts..., 92 ) 93 if err != nil { 94 logOperationFailure(fmt.Sprintf("Could not complete %s", "InsertMany"), err.Error()) 95 coll.tracer.AddExceptionTypeAndMessage( 96 "mongo-driver", 97 err.Error(), 98 ) 99 } 100 101 if event != nil { 102 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 103 marshalToMetadata(event.Resource.Metadata, "documents", documents, config) 104 marshalToMetadata(event.Resource.Metadata, "response", *response, config) 105 } 106 completeMongoEvent(coll.tracer, event) 107 } 108 return response, err 109 } 110 111 func (coll *MongoCollectionWrapper) BulkWrite( 112 ctx context.Context, models []mongo.WriteModel, opts ...*mongoOptions.BulkWriteOptions, 113 ) (*mongo.BulkWriteResult, error) { 114 event := startMongoEvent("BulkWrite", coll) 115 response, err := coll.collection.BulkWrite( 116 ctx, 117 models, 118 opts..., 119 ) 120 if err != nil { 121 logOperationFailure(fmt.Sprint("Could not complete BulkWrite"), err.Error()) 122 coll.tracer.AddExceptionTypeAndMessage( 123 "mongo-driver", 124 err.Error(), 125 ) 126 } 127 128 if event != nil { 129 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 130 marshalToMetadata(event.Resource.Metadata, "documents", models, config) 131 } 132 completeMongoEvent(coll.tracer, event) 133 } 134 return response, err 135 } 136 137 func (coll *MongoCollectionWrapper) DeleteOne( 138 ctx context.Context, filter interface{}, opts ...*mongoOptions.DeleteOptions, 139 ) (*mongo.DeleteResult, error) { 140 event := startMongoEvent("DeleteOne", coll) 141 response, err := coll.collection.DeleteOne( 142 ctx, 143 filter, 144 opts..., 145 ) 146 if err != nil { 147 logOperationFailure(fmt.Sprint("Could not complete DeleteOne"), err.Error()) 148 coll.tracer.AddExceptionTypeAndMessage( 149 "mongo-driver", 150 err.Error(), 151 ) 152 } 153 154 if event != nil { 155 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 156 marshalToMetadata(event.Resource.Metadata, "params", filter, config) 157 marshalToMetadata(event.Resource.Metadata, "response", *response, config) 158 } 159 completeMongoEvent(coll.tracer, event) 160 } 161 return response, err 162 } 163 164 func (coll *MongoCollectionWrapper) DeleteMany( 165 ctx context.Context, filter interface{}, opts ...*mongoOptions.DeleteOptions, 166 ) (*mongo.DeleteResult, error) { 167 event := startMongoEvent("DeleteMany", coll) 168 response, err := coll.collection.DeleteMany( 169 ctx, 170 filter, 171 opts..., 172 ) 173 if err != nil { 174 logOperationFailure(fmt.Sprintf("Could not complete DeleteMany"), err.Error()) 175 coll.tracer.AddExceptionTypeAndMessage( 176 "mongo-driver", 177 err.Error(), 178 ) 179 } 180 181 if event != nil { 182 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 183 marshalToMetadata(event.Resource.Metadata, "params", filter, config) 184 marshalToMetadata(event.Resource.Metadata, "response", response, config) 185 } 186 completeMongoEvent(coll.tracer, event) 187 } 188 return response, err 189 } 190 191 func (coll *MongoCollectionWrapper) UpdateOne( 192 ctx context.Context, filter interface{}, update interface{}, opts ...*mongoOptions.UpdateOptions, 193 ) (*mongo.UpdateResult, error) { 194 event := startMongoEvent("UpdateOne", coll) 195 response, err := coll.collection.UpdateOne( 196 ctx, 197 filter, 198 update, 199 opts..., 200 ) 201 if err != nil { 202 logOperationFailure(fmt.Sprintf("Could not complete %s", "UpdateOne"), err.Error()) 203 coll.tracer.AddExceptionTypeAndMessage( 204 "mongo-driver", 205 err.Error(), 206 ) 207 } 208 209 if event != nil { 210 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 211 marshalToMetadata(event.Resource.Metadata, "filter", filter, config) 212 marshalToMetadata(event.Resource.Metadata, "update_conditions", update, config) 213 extractStructFields(event.Resource.Metadata, "response", *response) 214 } 215 completeMongoEvent(coll.tracer, event) 216 } 217 return response, err 218 } 219 220 func (coll *MongoCollectionWrapper) UpdateMany( 221 ctx context.Context, filter interface{}, update interface{}, opts ...*mongoOptions.UpdateOptions, 222 ) (*mongo.UpdateResult, error) { 223 event := startMongoEvent("UpdateMany", coll) 224 response, err := coll.collection.UpdateMany( 225 ctx, 226 filter, 227 update, 228 opts..., 229 ) 230 if err != nil { 231 logOperationFailure(fmt.Sprintf("Could not complete %s", "UpdateMany"), err.Error()) 232 coll.tracer.AddExceptionTypeAndMessage( 233 "mongo-driver", 234 err.Error(), 235 ) 236 } 237 238 if event != nil { 239 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 240 marshalToMetadata(event.Resource.Metadata, "filter", filter, config) 241 marshalToMetadata(event.Resource.Metadata, "update_conditions", update, config) 242 extractStructFields(event.Resource.Metadata, "response", *response) 243 } 244 completeMongoEvent(coll.tracer, event) 245 } 246 return response, err 247 } 248 249 func (coll *MongoCollectionWrapper) UpdateByID( 250 ctx context.Context, id interface{}, update interface{}, opts ...*mongoOptions.UpdateOptions, 251 ) (*mongo.UpdateResult, error) { 252 event := startMongoEvent("UpdateByID", coll) 253 response, err := coll.collection.UpdateByID( 254 ctx, 255 id, 256 update, 257 opts..., 258 ) 259 if err != nil { 260 logOperationFailure(fmt.Sprintf("Could not complete %s", "UpdateByID"), err.Error()) 261 coll.tracer.AddExceptionTypeAndMessage( 262 "mongo-driver", 263 err.Error(), 264 ) 265 } 266 267 if event != nil { 268 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 269 marshalToMetadata(event.Resource.Metadata, "id", id, config) 270 marshalToMetadata(event.Resource.Metadata, "update_conditions", update, config) 271 extractStructFields(event.Resource.Metadata, "response", response) 272 } 273 completeMongoEvent(coll.tracer, event) 274 } 275 return response, err 276 } 277 278 func (coll *MongoCollectionWrapper) ReplaceOne( 279 ctx context.Context, filter interface{}, replacement interface{}, opts ...*mongoOptions.ReplaceOptions, 280 ) (*mongo.UpdateResult, error) { 281 event := startMongoEvent("ReplaceOne", coll) 282 response, err := coll.collection.ReplaceOne( 283 ctx, 284 filter, 285 replacement, 286 opts..., 287 ) 288 if err != nil { 289 logOperationFailure(fmt.Sprintf("Could not complete %s", "ReplaceOne"), err.Error()) 290 coll.tracer.AddExceptionTypeAndMessage( 291 "mongo-driver", 292 err.Error(), 293 ) 294 } 295 296 if event != nil { 297 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 298 marshalToMetadata(event.Resource.Metadata, "filter", filter, config) 299 marshalToMetadata(event.Resource.Metadata, "replacement", replacement, config) 300 extractStructFields(event.Resource.Metadata, "response", *response) 301 } 302 completeMongoEvent(coll.tracer, event) 303 } 304 return response, err 305 } 306 307 func (coll *MongoCollectionWrapper) Aggregate( 308 ctx context.Context, pipeline interface{}, opts ...*mongoOptions.AggregateOptions, 309 ) (*mongo.Cursor, error) { 310 event := startMongoEvent("Aggregate", coll) 311 response, err := coll.collection.Aggregate( 312 ctx, 313 pipeline, 314 opts..., 315 ) 316 if err != nil { 317 logOperationFailure(fmt.Sprintf("Could not complete %s", "Aggregate"), err.Error()) 318 coll.tracer.AddExceptionTypeAndMessage( 319 "mongo-driver", 320 err.Error(), 321 ) 322 } 323 324 docs, err := readCursor(response) 325 if err != nil { 326 logOperationFailure("Could not complete readCursor", err.Error()) 327 } 328 329 if event != nil { 330 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 331 marshalToMetadata(event.Resource.Metadata, "params", pipeline, config) 332 marshalToMetadata(event.Resource.Metadata, "response", docs, config) 333 } 334 completeMongoEvent(coll.tracer, event) 335 } 336 return response, err 337 } 338 339 func (coll *MongoCollectionWrapper) CountDocuments( 340 ctx context.Context, filter interface{}, opts ...*mongoOptions.CountOptions, 341 ) (int64, error) { 342 event := startMongoEvent("CountDocuments", coll) 343 response, err := coll.collection.CountDocuments( 344 ctx, 345 filter, 346 opts..., 347 ) 348 if err != nil { 349 logOperationFailure(fmt.Sprintf("Could not complete %s", "CountDocuments"), err.Error()) 350 coll.tracer.AddExceptionTypeAndMessage( 351 "mongo-driver", 352 err.Error(), 353 ) 354 } 355 356 if event != nil { 357 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 358 marshalToMetadata(event.Resource.Metadata, "filter", filter, config) 359 } 360 event.Resource.Metadata["count"] = fmt.Sprintf("%d", response) 361 completeMongoEvent(coll.tracer, event) 362 } 363 return response, err 364 } 365 366 func (coll *MongoCollectionWrapper) EstimatedDocumentCount( 367 ctx context.Context, opts ...*mongoOptions.EstimatedDocumentCountOptions, 368 ) (int64, error) { 369 event := startMongoEvent("EstimatedDocumentCount", coll) 370 response, err := coll.collection.EstimatedDocumentCount( 371 ctx, 372 opts..., 373 ) 374 if err != nil { 375 logOperationFailure(fmt.Sprintf("Could not complete %s", "EstimatedDocumentCount"), err.Error()) 376 coll.tracer.AddExceptionTypeAndMessage( 377 "mongo-driver", 378 err.Error(), 379 ) 380 } 381 382 if event != nil { 383 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 384 event.Resource.Metadata["estimated_count"] = fmt.Sprintf("%d", response) 385 } 386 completeMongoEvent(coll.tracer, event) 387 } 388 return response, err 389 } 390 391 func (coll *MongoCollectionWrapper) Distinct( 392 ctx context.Context, fieldName string, filter interface{}, opts ...*mongoOptions.DistinctOptions, 393 ) ([]interface{}, error) { 394 event := startMongoEvent("Distinct", coll) 395 response, err := coll.collection.Distinct( 396 ctx, 397 fieldName, 398 filter, 399 opts..., 400 ) 401 if err != nil { 402 logOperationFailure(fmt.Sprintf("Could not complete %s", "Distinct"), err.Error()) 403 coll.tracer.AddExceptionTypeAndMessage( 404 "mongo-driver", 405 err.Error(), 406 ) 407 } 408 409 if event != nil { 410 event.Resource.Metadata["field_name"] = fieldName 411 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 412 marshalToMetadata(event.Resource.Metadata, "filter", filter, config) 413 } 414 completeMongoEvent(coll.tracer, event) 415 } 416 return response, err 417 } 418 419 func (coll *MongoCollectionWrapper) Find( 420 ctx context.Context, filter interface{}, opts ...*mongoOptions.FindOptions, 421 ) (*mongo.Cursor, error) { 422 event := startMongoEvent("Find", coll) 423 response, err := coll.collection.Find( 424 ctx, 425 filter, 426 opts..., 427 ) 428 if err != nil { 429 logOperationFailure(fmt.Sprintf("Could not complete %s", "Find"), err.Error()) 430 coll.tracer.AddExceptionTypeAndMessage( 431 "mongo-driver", 432 err.Error(), 433 ) 434 } 435 436 docs, err := readCursor(response) 437 if err != nil { 438 logOperationFailure("Could not complete readCursor", err.Error()) 439 } 440 441 if event != nil { 442 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 443 marshalToMetadata(event.Resource.Metadata, "filter", filter, config) 444 marshalToMetadata(event.Resource.Metadata, "documents", docs, config) 445 } 446 completeMongoEvent(coll.tracer, event) 447 } 448 return response, err 449 } 450 451 func (coll *MongoCollectionWrapper) FindOne( 452 ctx context.Context, filter interface{}, opts ...*mongoOptions.FindOneOptions, 453 ) *mongo.SingleResult { 454 event := startMongoEvent("FindOne", coll) 455 response := coll.collection.FindOne( 456 ctx, 457 filter, 458 opts..., 459 ) 460 461 var document map[string]string 462 response.Decode(&document) 463 464 if err := response.Err(); err != nil { 465 logOperationFailure("Could not complete Decode SingleResult", err.Error()) 466 coll.tracer.AddExceptionTypeAndMessage( 467 "mongo-driver", 468 err.Error(), 469 ) 470 } 471 472 if event != nil { 473 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 474 marshalToMetadata(event.Resource.Metadata, "params", filter, config) 475 marshalToMetadata(event.Resource.Metadata, "document", document, config) 476 } 477 completeMongoEvent(coll.tracer, event) 478 } 479 return response 480 } 481 482 func (coll *MongoCollectionWrapper) FindOneAndDelete( 483 ctx context.Context, filter interface{}, opts ...*mongoOptions.FindOneAndDeleteOptions, 484 ) *mongo.SingleResult { 485 event := startMongoEvent("FindOneAndDelete", coll) 486 response := coll.collection.FindOneAndDelete( 487 ctx, 488 filter, 489 opts..., 490 ) 491 492 var document map[string]string 493 response.Decode(&document) 494 if err := response.Err(); err != nil { 495 logOperationFailure("Could not complete Decode SingleResult", err.Error()) 496 coll.tracer.AddExceptionTypeAndMessage( 497 "mongo-driver", 498 err.Error(), 499 ) 500 } 501 502 if event != nil { 503 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 504 marshalToMetadata(event.Resource.Metadata, "params", filter, config) 505 marshalToMetadata(event.Resource.Metadata, "document", document, config) 506 } 507 completeMongoEvent(coll.tracer, event) 508 } 509 return response 510 } 511 512 func (coll *MongoCollectionWrapper) FindOneAndReplace( 513 ctx context.Context, filter interface{}, replacement interface{}, opts ...*mongoOptions.FindOneAndReplaceOptions, 514 ) *mongo.SingleResult { 515 event := startMongoEvent("FindOneAndReplace", coll) 516 response := coll.collection.FindOneAndReplace( 517 ctx, 518 filter, 519 replacement, 520 opts..., 521 ) 522 var document map[string]string 523 response.Decode(&document) 524 525 if err := response.Err(); err != nil { 526 logOperationFailure("Could not complete Decode SingleResult", err.Error()) 527 coll.tracer.AddExceptionTypeAndMessage( 528 "mongo-driver", 529 err.Error(), 530 ) 531 } 532 533 if event != nil { 534 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 535 marshalToMetadata(event.Resource.Metadata, "filter", filter, config) 536 marshalToMetadata(event.Resource.Metadata, "replacement", replacement, config) 537 marshalToMetadata(event.Resource.Metadata, "document", document, config) 538 } 539 completeMongoEvent(coll.tracer, event) 540 } 541 return response 542 543 } 544 545 func (coll *MongoCollectionWrapper) FindOneAndUpdate( 546 ctx context.Context, filter interface{}, update interface{}, opts ...*mongoOptions.FindOneAndReplaceOptions, 547 ) *mongo.SingleResult { 548 event := startMongoEvent("FindOneAndUpdate", coll) 549 response := coll.collection.FindOneAndReplace( 550 ctx, 551 filter, 552 update, 553 opts..., 554 ) 555 var document map[string]string 556 response.Decode(&document) 557 if err := response.Err(); err != nil { 558 logOperationFailure("Could not complete Decode SingleResult", err.Error()) 559 coll.tracer.AddExceptionTypeAndMessage( 560 "mongo-driver", 561 err.Error(), 562 ) 563 } 564 if event != nil { 565 if config := coll.tracer.GetConfig(); !config.MetadataOnly { 566 marshalToMetadata(event.Resource.Metadata, "filter", filter, config) 567 marshalToMetadata(event.Resource.Metadata, "update", update, config) 568 marshalToMetadata(event.Resource.Metadata, "document", document, config) 569 } 570 completeMongoEvent(coll.tracer, event) 571 } 572 return response 573 } 574 575 func (coll *MongoCollectionWrapper) Drop(ctx context.Context) error { 576 event := startMongoEvent(currentFuncName(), coll) 577 err := coll.collection.Drop( 578 ctx, 579 ) 580 if err != nil { 581 logOperationFailure(fmt.Sprintf("Could not complete %s", "Drop"), err.Error()) 582 coll.tracer.AddExceptionTypeAndMessage( 583 "mongo-driver", 584 err.Error(), 585 ) 586 } 587 if event != nil { 588 completeMongoEvent(coll.tracer, event) 589 } 590 return err 591 } 592 593 func (coll *MongoCollectionWrapper) Indexes() mongo.IndexView { 594 event := startMongoEvent("Indexes", coll) 595 indexView := coll.collection.Indexes() 596 if event != nil { 597 completeMongoEvent(coll.tracer, event) 598 } 599 return indexView 600 } 601 602 func (coll *MongoCollectionWrapper) Watch( 603 ctx context.Context, pipeline interface{}, opts ...*mongoOptions.ChangeStreamOptions, 604 ) (*mongo.ChangeStream, error) { 605 event := startMongoEvent("Watch", coll) 606 response, err := coll.collection.Watch( 607 ctx, 608 pipeline, 609 opts..., 610 ) 611 if err != nil { 612 logOperationFailure(fmt.Sprintf("Could not complete %s", "Watch"), err.Error()) 613 coll.tracer.AddExceptionTypeAndMessage( 614 "mongo-driver", 615 err.Error(), 616 ) 617 } 618 if event != nil { 619 completeMongoEvent(coll.tracer, event) 620 } 621 return response, err 622 }