diff --git a/specifications/open-telemetry/operation/aggregate.json b/specifications/open-telemetry/operation/aggregate.json
new file mode 100644
index 00000000000..ac42cc8be65
--- /dev/null
+++ b/specifications/open-telemetry/operation/aggregate.json
@@ -0,0 +1,127 @@
+{
+ "description": "operation aggregate",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-aggregate"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "aggregation",
+ "operations": [
+ {
+ "name": "aggregate",
+ "object": "collection0",
+ "arguments": {
+ "pipeline": [
+ {
+ "$match": {
+ "_id": 1
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "aggregate operation-aggregate.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-aggregate",
+ "db.collection.name": "test",
+ "db.operation.name": "aggregate",
+ "db.operation.summary": "aggregate operation-aggregate.test"
+ },
+ "nested": [
+ {
+ "name": "aggregate",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-aggregate",
+ "db.collection.name": "test",
+ "db.command.name": "aggregate",
+ "network.transport": "tcp",
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "aggregate operation-aggregate.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "aggregate": "test",
+ "pipeline": [
+ {
+ "$match": {
+ "_id": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/aggregate.yml b/specifications/open-telemetry/operation/aggregate.yml
new file mode 100644
index 00000000000..630000f4414
--- /dev/null
+++ b/specifications/open-telemetry/operation/aggregate.yml
@@ -0,0 +1,62 @@
+description: operation aggregate
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-aggregate
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: &collectionName0 test
+
+tests:
+ - description: aggregation
+ operations:
+ - name: aggregate
+ object: *collection0
+ arguments:
+ pipeline: &pipeline0
+ - $match: { _id: 1 }
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: aggregate operation-aggregate.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-aggregate
+ db.collection.name: test
+ db.operation.name: aggregate
+ db.operation.summary: aggregate operation-aggregate.test
+
+ nested:
+ - name: aggregate
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-aggregate
+ db.collection.name: *collectionName0
+ db.command.name: aggregate
+ network.transport: tcp
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [int, long] }
+ db.query.summary: aggregate operation-aggregate.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ aggregate: test
+ pipeline: *pipeline0
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/atlas_search.json b/specifications/open-telemetry/operation/atlas_search.json
new file mode 100644
index 00000000000..0f236c2bed1
--- /dev/null
+++ b/specifications/open-telemetry/operation/atlas_search.json
@@ -0,0 +1,317 @@
+{
+ "description": "operation atlas_search",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-atlas-search"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "runOnRequirements": [
+ {
+ "minServerVersion": "7.0.5",
+ "maxServerVersion": "7.0.99",
+ "topologies": [
+ "replicaset",
+ "load-balanced",
+ "sharded"
+ ],
+ "serverless": "forbid"
+ },
+ {
+ "minServerVersion": "7.2.0",
+ "topologies": [
+ "replicaset",
+ "load-balanced",
+ "sharded"
+ ],
+ "serverless": "forbid"
+ }
+ ],
+ "tests": [
+ {
+ "description": "atlas search indexes",
+ "operations": [
+ {
+ "name": "createSearchIndex",
+ "object": "collection0",
+ "arguments": {
+ "model": {
+ "definition": {
+ "mappings": {
+ "dynamic": true
+ }
+ },
+ "type": "search"
+ }
+ },
+ "expectError": {
+ "isError": true,
+ "errorContains": "Atlas"
+ }
+ },
+ {
+ "name": "updateSearchIndex",
+ "object": "collection0",
+ "arguments": {
+ "name": "test index",
+ "definition": {}
+ },
+ "expectError": {
+ "isError": true,
+ "errorContains": "Atlas"
+ }
+ },
+ {
+ "name": "dropSearchIndex",
+ "object": "collection0",
+ "arguments": {
+ "name": "test index"
+ },
+ "expectError": {
+ "isError": true,
+ "errorContains": "Atlas"
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "createSearchIndexes operation-atlas-search.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-atlas-search",
+ "db.collection.name": "test",
+ "db.operation.name": "createSearchIndexes",
+ "db.operation.summary": "createSearchIndexes operation-atlas-search.test"
+ },
+ "nested": [
+ {
+ "name": "createSearchIndexes",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-atlas-search",
+ "db.command.name": "createSearchIndexes",
+ "db.collection.name": "test",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": true
+ },
+ "network.transport": "tcp",
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "exception.message": {
+ "$$exists": true
+ },
+ "exception.type": {
+ "$$exists": true
+ },
+ "exception.stacktrace": {
+ "$$exists": true
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.query.summary": "createSearchIndexes operation-atlas-search.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "createSearchIndexes": "test",
+ "indexes": [
+ {
+ "type": "search",
+ "definition": {
+ "mappings": {
+ "dynamic": true
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "updateSearchIndex operation-atlas-search.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-atlas-search",
+ "db.collection.name": "test",
+ "db.operation.name": "updateSearchIndex",
+ "db.operation.summary": "updateSearchIndex operation-atlas-search.test"
+ },
+ "nested": [
+ {
+ "name": "updateSearchIndex",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-atlas-search",
+ "db.command.name": "updateSearchIndex",
+ "db.collection.name": "test",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": true
+ },
+ "exception.message": {
+ "$$exists": true
+ },
+ "exception.type": {
+ "$$exists": true
+ },
+ "exception.stacktrace": {
+ "$$exists": true
+ },
+ "network.transport": "tcp",
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "updateSearchIndex operation-atlas-search.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "updateSearchIndex": "test",
+ "name": "test index",
+ "definition": {}
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "dropSearchIndex operation-atlas-search.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-atlas-search",
+ "db.collection.name": "test",
+ "db.operation.name": "dropSearchIndex",
+ "db.operation.summary": "dropSearchIndex operation-atlas-search.test"
+ },
+ "nested": [
+ {
+ "name": "dropSearchIndex",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-atlas-search",
+ "db.command.name": "dropSearchIndex",
+ "db.collection.name": "test",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": true
+ },
+ "exception.message": {
+ "$$exists": true
+ },
+ "exception.type": {
+ "$$exists": true
+ },
+ "exception.stacktrace": {
+ "$$exists": true
+ },
+ "network.transport": "tcp",
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "dropSearchIndex operation-atlas-search.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "dropSearchIndex": "test",
+ "name": "test index"
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/atlas_search.yml b/specifications/open-telemetry/operation/atlas_search.yml
new file mode 100644
index 00000000000..d5029f994f2
--- /dev/null
+++ b/specifications/open-telemetry/operation/atlas_search.yml
@@ -0,0 +1,170 @@
+description: operation atlas_search
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-atlas-search
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: test
+
+runOnRequirements:
+ # Skip server versions without fix of SERVER-83107 to avoid error message "BSON field 'createSearchIndexes.indexes.type' is an unknown field."
+ # SERVER-83107 was not backported to 7.1.
+ - minServerVersion: "7.0.5"
+ maxServerVersion: "7.0.99"
+ topologies: [ replicaset, load-balanced, sharded ]
+ serverless: forbid
+ - minServerVersion: "7.2.0"
+ topologies: [ replicaset, load-balanced, sharded ]
+ serverless: forbid
+
+
+tests:
+ - description: atlas search indexes
+ operations:
+ - name: createSearchIndex
+ object: *collection0
+ arguments:
+ model: { definition: { mappings: { dynamic: true } } , type: 'search' }
+ expectError:
+ # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting
+ # that the driver constructs and sends the correct command.
+ # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages.
+ isError: true
+ errorContains: Atlas
+
+ - name: updateSearchIndex
+ object: *collection0
+ arguments:
+ name: 'test index'
+ definition: {}
+ expectError:
+ # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting
+ # that the driver constructs and sends the correct command.
+ # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages.
+ isError: true
+ errorContains: Atlas
+
+ - name: dropSearchIndex
+ object: *collection0
+ arguments:
+ name: 'test index'
+ expectError:
+ # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting
+ # that the driver constructs and sends the correct command.
+ # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages.
+ isError: true
+ errorContains: Atlas
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: createSearchIndexes operation-atlas-search.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-atlas-search
+ db.collection.name: test
+ db.operation.name: createSearchIndexes
+ db.operation.summary: createSearchIndexes operation-atlas-search.test
+ nested:
+ - name: createSearchIndexes
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-atlas-search
+ db.command.name: createSearchIndexes
+ db.collection.name: test
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: true }
+ network.transport: tcp
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ exception.message: { $$exists: true }
+ exception.type: { $$exists: true }
+ exception.stacktrace: { $$exists: true }
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.query.summary: createSearchIndexes operation-atlas-search.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ createSearchIndexes: test
+ indexes: [ { "type": "search", "definition": { "mappings": { "dynamic": true } } } ]
+
+ - name: updateSearchIndex operation-atlas-search.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-atlas-search
+ db.collection.name: test
+ db.operation.name: updateSearchIndex
+ db.operation.summary: updateSearchIndex operation-atlas-search.test
+
+ nested:
+ - name: updateSearchIndex
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-atlas-search
+ db.command.name: updateSearchIndex
+ db.collection.name: test
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: true }
+ exception.message: { $$exists: true }
+ exception.type: { $$exists: true }
+ exception.stacktrace: { $$exists: true }
+ network.transport: tcp
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.summary: updateSearchIndex operation-atlas-search.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ updateSearchIndex: test
+ name: test index
+ definition: {}
+
+ - name: dropSearchIndex operation-atlas-search.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-atlas-search
+ db.collection.name: test
+ db.operation.name: dropSearchIndex
+ db.operation.summary: dropSearchIndex operation-atlas-search.test
+ nested:
+ - name: dropSearchIndex
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-atlas-search
+ db.command.name: dropSearchIndex
+ db.collection.name: test
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: true }
+ exception.message: { $$exists: true }
+ exception.type: { $$exists: true }
+ exception.stacktrace: { $$exists: true }
+ network.transport: tcp
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.summary: dropSearchIndex operation-atlas-search.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ dropSearchIndex: test
+ name: test index
diff --git a/specifications/open-telemetry/operation/bulk_write.json b/specifications/open-telemetry/operation/bulk_write.json
new file mode 100644
index 00000000000..6f1e62004ac
--- /dev/null
+++ b/specifications/open-telemetry/operation/bulk_write.json
@@ -0,0 +1,333 @@
+{
+ "description": "operation bulk_write",
+ "schemaVersion": "1.27",
+ "runOnRequirements": [
+ {
+ "minServerVersion": "8.0",
+ "serverless": "forbid"
+ }
+ ],
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-bulk-write-0"
+ }
+ },
+ {
+ "database": {
+ "id": "database1",
+ "client": "client0",
+ "databaseName": "operation-bulk-write-1"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test0"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection1",
+ "database": "database1",
+ "collectionName": "test1"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test0",
+ "databaseName": "operation-bulk-write-0",
+ "documents": []
+ },
+ {
+ "collectionName": "test1",
+ "databaseName": "operation-bulk-write-1",
+ "documents": []
+ }
+ ],
+ "_yamlAnchors": {
+ "namespace0": "operation-bulk-write-0.test0",
+ "namespace1": "operation-bulk-write-1.test1"
+ },
+ "tests": [
+ {
+ "description": "bulkWrite",
+ "operations": [
+ {
+ "object": "client0",
+ "name": "clientBulkWrite",
+ "arguments": {
+ "models": [
+ {
+ "insertOne": {
+ "namespace": "operation-bulk-write-0.test0",
+ "document": {
+ "_id": 8,
+ "x": 88
+ }
+ }
+ },
+ {
+ "updateOne": {
+ "namespace": "operation-bulk-write-0.test0",
+ "filter": {
+ "_id": 1
+ },
+ "update": {
+ "$inc": {
+ "x": 1
+ }
+ }
+ }
+ },
+ {
+ "updateMany": {
+ "namespace": "operation-bulk-write-1.test1",
+ "filter": {
+ "$and": [
+ {
+ "_id": {
+ "$gt": 1
+ }
+ },
+ {
+ "_id": {
+ "$lte": 3
+ }
+ }
+ ]
+ },
+ "update": {
+ "$inc": {
+ "x": 2
+ }
+ }
+ }
+ },
+ {
+ "replaceOne": {
+ "namespace": "operation-bulk-write-1.test1",
+ "filter": {
+ "_id": 4
+ },
+ "replacement": {
+ "x": 44
+ },
+ "upsert": true
+ }
+ },
+ {
+ "deleteOne": {
+ "namespace": "operation-bulk-write-0.test0",
+ "filter": {
+ "_id": 5
+ }
+ }
+ },
+ {
+ "deleteMany": {
+ "namespace": "operation-bulk-write-1.test1",
+ "filter": {
+ "$and": [
+ {
+ "_id": {
+ "$gt": 5
+ }
+ },
+ {
+ "_id": {
+ "$lte": 7
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "bulkWrite admin",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.operation.name": "bulkWrite",
+ "db.operation.summary": "bulkWrite admin"
+ },
+ "nested": [
+ {
+ "name": "bulkWrite",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.command.name": "bulkWrite",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "bulkWrite admin",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "bulkWrite": 1,
+ "errorsOnly": true,
+ "ordered": true,
+ "ops": [
+ {
+ "insert": 0,
+ "document": {
+ "_id": 8,
+ "x": 88
+ }
+ },
+ {
+ "update": 0,
+ "multi": false,
+ "filter": {
+ "_id": 1
+ },
+ "updateMods": {
+ "$inc": {
+ "x": 1
+ }
+ }
+ },
+ {
+ "update": 1,
+ "multi": true,
+ "filter": {
+ "$and": [
+ {
+ "_id": {
+ "$gt": 1
+ }
+ },
+ {
+ "_id": {
+ "$lte": 3
+ }
+ }
+ ]
+ },
+ "updateMods": {
+ "$inc": {
+ "x": 2
+ }
+ }
+ },
+ {
+ "update": 1,
+ "multi": false,
+ "filter": {
+ "_id": 4
+ },
+ "updateMods": {
+ "x": 44
+ },
+ "upsert": true
+ },
+ {
+ "delete": 0,
+ "multi": false,
+ "filter": {
+ "_id": 5
+ }
+ },
+ {
+ "delete": 1,
+ "multi": true,
+ "filter": {
+ "$and": [
+ {
+ "_id": {
+ "$gt": 5
+ }
+ },
+ {
+ "_id": {
+ "$lte": 7
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "nsInfo": [
+ {
+ "ns": "operation-bulk-write-0.test0"
+ },
+ {
+ "ns": "operation-bulk-write-1.test1"
+ }
+ ]
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/bulk_write.yml b/specifications/open-telemetry/operation/bulk_write.yml
new file mode 100644
index 00000000000..6f84e50fb15
--- /dev/null
+++ b/specifications/open-telemetry/operation/bulk_write.yml
@@ -0,0 +1,198 @@
+description: operation bulk_write
+schemaVersion: '1.27'
+runOnRequirements:
+ - minServerVersion: "8.0"
+ serverless: forbid
+
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: &databaseName0 operation-bulk-write-0
+ - database:
+ id: &database1 database1
+ client: *client0
+ databaseName: &databaseName1 operation-bulk-write-1
+ - collection:
+ id: collection0
+ database: *database0
+ collectionName: &collectionName0 test0
+ - collection:
+ id: collection1
+ database: *database1
+ collectionName: &collectionName1 test1
+
+initialData:
+ - collectionName: *collectionName0
+ databaseName: *databaseName0
+ documents: [ ]
+ - collectionName: *collectionName1
+ databaseName: *databaseName1
+ documents: [ ]
+
+_yamlAnchors:
+ namespace0: &namespace0 "operation-bulk-write-0.test0"
+ namespace1: &namespace1 "operation-bulk-write-1.test1"
+
+tests:
+ - description: bulkWrite
+ operations:
+ - object: *client0
+ name: clientBulkWrite
+ arguments:
+ models:
+ - insertOne:
+ namespace: *namespace0
+ document: { _id: 8, x: 88 }
+ - updateOne:
+ namespace: *namespace0
+ filter: { _id: 1 }
+ update: { $inc: { x: 1 } }
+ - updateMany:
+ namespace: *namespace1
+ filter:
+ $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ]
+ update: { $inc: { x: 2 } }
+ - replaceOne:
+ namespace: *namespace1
+ filter: { _id: 4 }
+ replacement: { x: 44 }
+ upsert: true
+ - deleteOne:
+ namespace: *namespace0
+ filter: { _id: 5 }
+ - deleteMany:
+ namespace: *namespace1
+ filter:
+ $and: [ { _id: { $gt: 5 } }, { _id: { $lte: 7 } } ]
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: bulkWrite admin
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.collection.name: { $$exists: false }
+ db.operation.name: bulkWrite
+ db.operation.summary: bulkWrite admin
+ nested:
+ - name: bulkWrite
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.collection.name: { $$exists: false }
+ db.command.name: bulkWrite
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.query.summary: bulkWrite admin
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ bulkWrite: 1
+ errorsOnly: true
+ ordered: true
+ ops: [
+ {
+ "insert": 0,
+ "document": {
+ "_id": 8,
+ "x": 88
+ }
+ },
+ {
+ "update": 0,
+ "multi": false,
+ "filter": {
+ "_id": 1
+ },
+ "updateMods": {
+ "$inc": {
+ "x": 1
+ }
+ }
+ },
+ {
+ "update": 1,
+ "multi": true,
+ "filter": {
+ "$and": [
+ {
+ "_id": {
+ "$gt": 1
+ }
+ },
+ {
+ "_id": {
+ "$lte": 3
+ }
+ }
+ ]
+ },
+ "updateMods": {
+ "$inc": {
+ "x": 2
+ }
+ }
+ },
+ {
+ "update": 1,
+ "multi": false,
+ "filter": {
+ "_id": 4
+ },
+ "updateMods": {
+ "x": 44
+ },
+ "upsert": true
+ },
+ {
+ "delete": 0,
+ "multi": false,
+ "filter": {
+ "_id": 5
+ }
+ },
+ {
+ "delete": 1,
+ "multi": true,
+ "filter": {
+ "$and": [
+ {
+ "_id": {
+ "$gt": 5
+ }
+ },
+ {
+ "_id": {
+ "$lte": 7
+ }
+ }
+ ]
+ }
+ }
+ ]
+ nsInfo: [
+ {
+ "ns": *namespace0
+ },
+ {
+ "ns": *namespace1
+ }
+ ]
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/count.json b/specifications/open-telemetry/operation/count.json
new file mode 100644
index 00000000000..6b4304dfd85
--- /dev/null
+++ b/specifications/open-telemetry/operation/count.json
@@ -0,0 +1,123 @@
+{
+ "description": "operation count",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-count"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "operation-count",
+ "documents": []
+ }
+ ],
+ "tests": [
+ {
+ "description": "estimated document count",
+ "operations": [
+ {
+ "object": "collection0",
+ "name": "estimatedDocumentCount",
+ "arguments": {},
+ "expectResult": 0
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "count operation-count.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-count",
+ "db.collection.name": "test",
+ "db.operation.name": "count",
+ "db.operation.summary": "count operation-count.test"
+ },
+ "nested": [
+ {
+ "name": "count",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-count",
+ "db.collection.name": "test",
+ "db.command.name": "count",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "count operation-count.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "count": "test"
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/count.yml b/specifications/open-telemetry/operation/count.yml
new file mode 100644
index 00000000000..3d2abcb04c8
--- /dev/null
+++ b/specifications/open-telemetry/operation/count.yml
@@ -0,0 +1,63 @@
+description: operation count
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: database0
+ client: *client0
+ databaseName: &database0Name operation-count
+ - collection:
+ id: &collection0 collection0
+ database: database0
+ collectionName: &collection0Name test
+initialData:
+ - collectionName: *collection0Name
+ databaseName: *database0Name
+ documents: []
+tests:
+ - description: estimated document count
+ operations:
+ - object: *collection0
+ name: estimatedDocumentCount
+ arguments: { }
+ expectResult: 0
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: count operation-count.test
+ attributes:
+ db.system: mongodb
+ db.namespace: *database0Name
+ db.collection.name: *collection0Name
+ db.operation.name: count
+ db.operation.summary: count operation-count.test
+ nested:
+ - name: count
+ attributes:
+ db.system: mongodb
+ db.namespace: *database0Name
+ db.collection.name: *collection0Name
+ db.command.name: count
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [int, long] }
+ db.query.summary: count operation-count.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ count: test
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/create_collection.json b/specifications/open-telemetry/operation/create_collection.json
new file mode 100644
index 00000000000..fc296b4fd22
--- /dev/null
+++ b/specifications/open-telemetry/operation/create_collection.json
@@ -0,0 +1,110 @@
+{
+ "description": "operation create collection",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-create-collection"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "create collection",
+ "operations": [
+ {
+ "object": "database0",
+ "name": "createCollection",
+ "arguments": {
+ "collection": "newlyCreatedCollection"
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "createCollection operation-create-collection.newlyCreatedCollection",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-create-collection",
+ "db.collection.name": "newlyCreatedCollection",
+ "db.operation.name": "createCollection",
+ "db.operation.summary": "createCollection operation-create-collection.newlyCreatedCollection"
+ },
+ "nested": [
+ {
+ "name": "create",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-create-collection",
+ "db.collection.name": "newlyCreatedCollection",
+ "db.command.name": "create",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "create operation-create-collection.newlyCreatedCollection",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "create": "newlyCreatedCollection"
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/create_collection.yml b/specifications/open-telemetry/operation/create_collection.yml
new file mode 100644
index 00000000000..d0dee36051a
--- /dev/null
+++ b/specifications/open-telemetry/operation/create_collection.yml
@@ -0,0 +1,55 @@
+description: operation create collection
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: &database0Name operation-create-collection
+tests:
+ - description: create collection
+ operations:
+ - object: *database0
+ name: createCollection
+ arguments:
+ collection: &collectionName newlyCreatedCollection
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: createCollection operation-create-collection.newlyCreatedCollection
+ attributes:
+ db.system: mongodb
+ db.namespace: *database0Name
+ db.collection.name: *collectionName
+ db.operation.name: createCollection
+ db.operation.summary: createCollection operation-create-collection.newlyCreatedCollection
+ nested:
+ - name: create
+ attributes:
+ db.system: mongodb
+ db.namespace: *database0Name
+ db.collection.name: *collectionName
+ db.command.name: create
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [int, long] }
+ db.query.summary: create operation-create-collection.newlyCreatedCollection
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ create: newlyCreatedCollection
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/create_indexes.json b/specifications/open-telemetry/operation/create_indexes.json
new file mode 100644
index 00000000000..40afac51479
--- /dev/null
+++ b/specifications/open-telemetry/operation/create_indexes.json
@@ -0,0 +1,127 @@
+{
+ "description": "operation create_indexes",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-create-indexes"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "create indexes",
+ "operations": [
+ {
+ "object": "collection0",
+ "name": "createIndex",
+ "arguments": {
+ "keys": {
+ "x": 1
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "createIndexes operation-create-indexes.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-create-indexes",
+ "db.collection.name": "test",
+ "db.operation.name": "createIndexes",
+ "db.operation.summary": "createIndexes operation-create-indexes.test"
+ },
+ "nested": [
+ {
+ "name": "createIndexes",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-create-indexes",
+ "db.collection.name": "test",
+ "db.command.name": "createIndexes",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "createIndexes operation-create-indexes.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "createIndexes": "test",
+ "indexes": [
+ {
+ "key": {
+ "x": 1
+ },
+ "name": "x_1"
+ }
+ ]
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/create_indexes.yml b/specifications/open-telemetry/operation/create_indexes.yml
new file mode 100644
index 00000000000..01e23e242cd
--- /dev/null
+++ b/specifications/open-telemetry/operation/create_indexes.yml
@@ -0,0 +1,60 @@
+description: operation create_indexes
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: &database0Name operation-create-indexes
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: &collection0Name test
+tests:
+ - description: create indexes
+ operations:
+ - object: *collection0
+ name: createIndex
+ arguments:
+ keys: { x: 1 }
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: createIndexes operation-create-indexes.test
+ attributes:
+ db.system: mongodb
+ db.namespace: *database0Name
+ db.collection.name: *collection0Name
+ db.operation.name: createIndexes
+ db.operation.summary: createIndexes operation-create-indexes.test
+ nested:
+ - name: createIndexes
+ attributes:
+ db.system: mongodb
+ db.namespace: *database0Name
+ db.collection.name: *collection0Name
+ db.command.name: createIndexes
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [int, long] }
+ db.query.summary: createIndexes operation-create-indexes.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ createIndexes: test
+ indexes: [ { key: { x: 1 }, name: "x_1" } ]
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/delete.json b/specifications/open-telemetry/operation/delete.json
new file mode 100644
index 00000000000..203e392ce88
--- /dev/null
+++ b/specifications/open-telemetry/operation/delete.json
@@ -0,0 +1,132 @@
+{
+ "description": "operation delete",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-delete"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "delete elements",
+ "operations": [
+ {
+ "object": "collection0",
+ "name": "deleteMany",
+ "arguments": {
+ "filter": {
+ "_id": {
+ "$gt": 1
+ }
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "delete operation-delete.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-delete",
+ "db.collection.name": "test",
+ "db.operation.name": "delete",
+ "db.operation.summary": "delete operation-delete.test"
+ },
+ "nested": [
+ {
+ "name": "delete",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.command.name": "delete",
+ "db.namespace": "operation-delete",
+ "db.collection.name": "test",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "network.transport": "tcp",
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "delete operation-delete.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "delete": "test",
+ "ordered": true,
+ "deletes": [
+ {
+ "q": {
+ "_id": {
+ "$gt": 1
+ }
+ },
+ "limit": 0
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/delete.yml b/specifications/open-telemetry/operation/delete.yml
new file mode 100644
index 00000000000..94410683f96
--- /dev/null
+++ b/specifications/open-telemetry/operation/delete.yml
@@ -0,0 +1,62 @@
+description: operation delete
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: &databaseName0 operation-delete
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: &collectionName0 test
+
+tests:
+ - description: delete elements
+ operations:
+ - object: *collection0
+ name: deleteMany
+ arguments:
+ filter: { _id: { $gt: 1 } }
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: delete operation-delete.test
+ attributes:
+ db.system: mongodb
+ db.namespace: *databaseName0
+ db.collection.name: *collectionName0
+ db.operation.name: delete
+ db.operation.summary: delete operation-delete.test
+ nested:
+ - name: delete
+ attributes:
+ db.system: mongodb
+ db.command.name: delete
+ db.namespace: operation-delete
+ db.collection.name: test
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ network.transport: tcp
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.summary: delete operation-delete.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ delete: test
+ ordered: true
+ deletes: [ { q: { _id: { $gt: 1 } }, limit: 0 } ]
diff --git a/specifications/open-telemetry/operation/distinct.json b/specifications/open-telemetry/operation/distinct.json
new file mode 100644
index 00000000000..8478d569fee
--- /dev/null
+++ b/specifications/open-telemetry/operation/distinct.json
@@ -0,0 +1,127 @@
+{
+ "description": "operation distinct",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-distinct"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "operation-distinct",
+ "documents": []
+ }
+ ],
+ "tests": [
+ {
+ "description": "distinct on a field",
+ "operations": [
+ {
+ "object": "collection0",
+ "name": "distinct",
+ "arguments": {
+ "fieldName": "x",
+ "filter": {}
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "distinct operation-distinct.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-distinct",
+ "db.collection.name": "test",
+ "db.operation.name": "distinct",
+ "db.operation.summary": "distinct operation-distinct.test"
+ },
+ "nested": [
+ {
+ "name": "distinct",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-distinct",
+ "db.collection.name": "test",
+ "db.command.name": "distinct",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "distinct operation-distinct.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "distinct": "test",
+ "key": "x",
+ "query": {}
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/distinct.yml b/specifications/open-telemetry/operation/distinct.yml
new file mode 100644
index 00000000000..0b78cecca9d
--- /dev/null
+++ b/specifications/open-telemetry/operation/distinct.yml
@@ -0,0 +1,66 @@
+description: operation distinct
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: database0
+ client: *client0
+ databaseName: operation-distinct
+ - collection:
+ id: &collection0 collection0
+ database: database0
+ collectionName: test
+initialData:
+ - collectionName: test
+ databaseName: operation-distinct
+ documents: []
+tests:
+ - description: distinct on a field
+ operations:
+ - object: *collection0
+ name: distinct
+ arguments:
+ fieldName: x
+ filter: {}
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: distinct operation-distinct.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-distinct
+ db.collection.name: test
+ db.operation.name: distinct
+ db.operation.summary: distinct operation-distinct.test
+ nested:
+ - name: distinct
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-distinct
+ db.collection.name: test
+ db.command.name: distinct
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [int, long] }
+ db.query.summary: distinct operation-distinct.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ distinct: test
+ key: x
+ query: { }
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/drop_collection.json b/specifications/open-telemetry/operation/drop_collection.json
new file mode 100644
index 00000000000..fbffed165bd
--- /dev/null
+++ b/specifications/open-telemetry/operation/drop_collection.json
@@ -0,0 +1,122 @@
+{
+ "description": "operation drop collection",
+ "schemaVersion": "1.27",
+ "runOnRequirements": [
+ {
+ "minServerVersion": "7.0"
+ }
+ ],
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-drop-collection"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "drop collection",
+ "operations": [
+ {
+ "object": "database0",
+ "name": "dropCollection",
+ "arguments": {
+ "collection": "test"
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "dropCollection operation-drop-collection.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-drop-collection",
+ "db.collection.name": "test",
+ "db.operation.name": "dropCollection",
+ "db.operation.summary": "dropCollection operation-drop-collection.test"
+ },
+ "nested": [
+ {
+ "name": "drop",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-drop-collection",
+ "db.collection.name": "test",
+ "db.command.name": "drop",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "drop operation-drop-collection.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "drop": "test"
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/drop_collection.yml b/specifications/open-telemetry/operation/drop_collection.yml
new file mode 100644
index 00000000000..7308c83b5ec
--- /dev/null
+++ b/specifications/open-telemetry/operation/drop_collection.yml
@@ -0,0 +1,65 @@
+description: operation drop collection
+schemaVersion: '1.27'
+
+runOnRequirements:
+ - minServerVersion: "7.0"
+
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-drop-collection
+
+ - collection:
+ id: collection0
+ database: *database0
+ collectionName: &collection_name test
+tests:
+ - description: drop collection
+ operations:
+ - object: *database0
+ name: dropCollection
+ arguments:
+ collection: *collection_name
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: dropCollection operation-drop-collection.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-drop-collection
+ db.collection.name: test
+ db.operation.name: dropCollection
+ db.operation.summary: dropCollection operation-drop-collection.test
+
+ nested:
+ - name: drop
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-drop-collection
+ db.collection.name: test
+ db.command.name: drop
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [int, long] }
+ db.query.summary: drop operation-drop-collection.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ drop: test
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/drop_indexes.json b/specifications/open-telemetry/operation/drop_indexes.json
new file mode 100644
index 00000000000..efc865b3226
--- /dev/null
+++ b/specifications/open-telemetry/operation/drop_indexes.json
@@ -0,0 +1,145 @@
+{
+ "description": "operation drop indexes",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-drop-indexes"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ },
+ {
+ "client": {
+ "id": "clientWithoutTracing",
+ "useMultipleMongoses": false
+ }
+ },
+ {
+ "database": {
+ "id": "databaseWithoutTracing",
+ "client": "clientWithoutTracing",
+ "databaseName": "operation-drop-indexes"
+ }
+ },
+ {
+ "collection": {
+ "id": "collectionWithoutTracing",
+ "database": "databaseWithoutTracing",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "drop indexes",
+ "operations": [
+ {
+ "name": "createIndex",
+ "object": "collectionWithoutTracing",
+ "arguments": {
+ "keys": {
+ "x": 1
+ },
+ "name": "x_1"
+ }
+ },
+ {
+ "name": "dropIndexes",
+ "object": "collection0"
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": true,
+ "spans": [
+ {
+ "name": "dropIndexes operation-drop-indexes.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-drop-indexes",
+ "db.collection.name": "test",
+ "db.operation.name": "dropIndexes",
+ "db.operation.summary": "dropIndexes operation-drop-indexes.test"
+ },
+ "nested": [
+ {
+ "name": "dropIndexes",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-drop-indexes",
+ "db.collection.name": "test",
+ "db.command.name": "dropIndexes",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "dropIndexes operation-drop-indexes.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "dropIndexes": "test",
+ "index": "*"
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/drop_indexes.yml b/specifications/open-telemetry/operation/drop_indexes.yml
new file mode 100644
index 00000000000..519995b7436
--- /dev/null
+++ b/specifications/open-telemetry/operation/drop_indexes.yml
@@ -0,0 +1,78 @@
+description: operation drop indexes
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-drop-indexes
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: test
+ - client:
+ id: &clientWithoutTracing clientWithoutTracing
+ useMultipleMongoses: false
+ - database:
+ id: &databaseWithoutTracing databaseWithoutTracing
+ client: *clientWithoutTracing
+ databaseName: operation-drop-indexes
+ - collection:
+ id: &collectionWithoutTracing collectionWithoutTracing
+ database: *databaseWithoutTracing
+ collectionName: test
+
+tests:
+ - description: drop indexes
+ operations:
+ - name: createIndex
+ object: *collectionWithoutTracing
+ arguments:
+ keys:
+ x: 1
+ name: x_1
+
+ - name: dropIndexes
+ object: *collection0
+
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: true
+ spans:
+ - name: dropIndexes operation-drop-indexes.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-drop-indexes
+ db.collection.name: test
+ db.operation.name: dropIndexes
+ db.operation.summary: dropIndexes operation-drop-indexes.test
+ nested:
+ - name: dropIndexes
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-drop-indexes
+ db.collection.name: test
+ db.command.name: dropIndexes
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [int, long] }
+ db.query.summary: dropIndexes operation-drop-indexes.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ dropIndexes: test
+ index: '*'
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/find.json b/specifications/open-telemetry/operation/find.json
new file mode 100644
index 00000000000..573fd75411b
--- /dev/null
+++ b/specifications/open-telemetry/operation/find.json
@@ -0,0 +1,291 @@
+{
+ "description": "operation find",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-find"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "operation-find",
+ "documents": []
+ }
+ ],
+ "tests": [
+ {
+ "description": "find an element",
+ "operations": [
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "find operation-find.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-find",
+ "db.collection.name": "test",
+ "db.operation.name": "find",
+ "db.operation.summary": "find operation-find.test"
+ },
+ "nested": [
+ {
+ "name": "find",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-find",
+ "db.collection.name": "test",
+ "db.command.name": "find",
+ "network.transport": "tcp",
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "find operation-find.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "find": "test",
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "description": "find an element retrying failed command",
+ "operations": [
+ {
+ "name": "failPoint",
+ "object": "testRunner",
+ "arguments": {
+ "client": "client0",
+ "failPoint": {
+ "configureFailPoint": "failCommand",
+ "mode": {
+ "times": 1
+ },
+ "data": {
+ "failCommands": [
+ "find"
+ ],
+ "errorCode": 89,
+ "errorLabels": [
+ "RetryableWriteError"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": true,
+ "spans": [
+ {
+ "name": "find operation-find.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-find",
+ "db.collection.name": "test",
+ "db.operation.name": "find",
+ "db.operation.summary": "find operation-find.test"
+ },
+ "nested": [
+ {
+ "name": "find",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-find",
+ "db.collection.name": "test",
+ "db.command.name": "find",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": "89",
+ "exception.message": {
+ "$$type": "string"
+ },
+ "exception.type": {
+ "$$type": "string"
+ },
+ "exception.stacktrace": {
+ "$$type": "string"
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.query.summary": "find operation-find.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "find": "test",
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ },
+ {
+ "name": "find",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-find",
+ "db.collection.name": "test",
+ "db.command.name": "find",
+ "network.transport": "tcp",
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "find operation-find.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "find": "test",
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/find.yml b/specifications/open-telemetry/operation/find.yml
new file mode 100644
index 00000000000..c29bc0123a1
--- /dev/null
+++ b/specifications/open-telemetry/operation/find.yml
@@ -0,0 +1,143 @@
+description: operation find
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-find
+ - collection:
+ id: &collection0 collection0
+ database: database0
+ collectionName: &collection0Name test
+initialData:
+ - collectionName: test
+ databaseName: operation-find
+ documents: []
+tests:
+ - description: find an element
+ operations:
+ - name: find
+ object: *collection0
+ arguments: { filter: { x: 1 } }
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: find operation-find.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-find
+ db.collection.name: test
+ db.operation.name: find
+ db.operation.summary: find operation-find.test
+ nested:
+ - name: find
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-find
+ db.collection.name: test
+ db.command.name: find
+ network.transport: tcp
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [int, long] }
+ db.query.summary: find operation-find.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ find: test
+ filter:
+ x: 1
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+
+ - description: find an element retrying failed command
+ operations:
+ - name: failPoint
+ object: testRunner
+ arguments:
+ client: *client0
+ failPoint:
+ configureFailPoint: failCommand
+ mode: { times: 1 }
+ data:
+ failCommands: [ find ]
+ errorCode: 89
+ errorLabels: [ RetryableWriteError ]
+
+ - name: find
+ object: *collection0
+ arguments:
+ filter: { x: 1 }
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: true
+ spans:
+ - name: find operation-find.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-find
+ db.collection.name: test
+ db.operation.name: find
+ db.operation.summary: find operation-find.test
+ nested:
+ - name: find
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-find
+ db.collection.name: test
+ db.command.name: find
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: '89'
+ exception.message: { $$type: string }
+ exception.type: { $$type: string }
+ exception.stacktrace: { $$type: string }
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.query.summary: find operation-find.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ find: test
+ filter:
+ x: 1
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ - name: find
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-find
+ db.collection.name: test
+ db.command.name: find
+ network.transport: tcp
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.query.summary: find operation-find.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ find: test
+ filter:
+ x: 1
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/find_and_modify.json b/specifications/open-telemetry/operation/find_and_modify.json
new file mode 100644
index 00000000000..26e45b1deda
--- /dev/null
+++ b/specifications/open-telemetry/operation/find_and_modify.json
@@ -0,0 +1,143 @@
+{
+ "description": "operation find_one_and_update",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-find-one-and-update"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "findOneAndUpdate",
+ "runOnRequirements": [
+ {
+ "minServerVersion": "4.4"
+ }
+ ],
+ "operations": [
+ {
+ "name": "findOneAndUpdate",
+ "object": "collection0",
+ "arguments": {
+ "filter": {
+ "_id": 1
+ },
+ "update": [
+ {
+ "$set": {
+ "x": 5
+ }
+ }
+ ],
+ "comment": "comment"
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "findAndModify operation-find-one-and-update.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-find-one-and-update",
+ "db.collection.name": "test",
+ "db.operation.name": "findAndModify",
+ "db.operation.summary": "findAndModify operation-find-one-and-update.test"
+ },
+ "nested": [
+ {
+ "name": "findAndModify",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-find-one-and-update",
+ "db.collection.name": "test",
+ "db.command.name": "findAndModify",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "findAndModify operation-find-one-and-update.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "findAndModify": "test",
+ "query": {
+ "_id": 1
+ },
+ "update": [
+ {
+ "$set": {
+ "x": 5
+ }
+ }
+ ],
+ "comment": "comment"
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/find_and_modify.yml b/specifications/open-telemetry/operation/find_and_modify.yml
new file mode 100644
index 00000000000..7959d4880ec
--- /dev/null
+++ b/specifications/open-telemetry/operation/find_and_modify.yml
@@ -0,0 +1,70 @@
+description: operation find_one_and_update
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-find-one-and-update
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: test
+
+tests:
+ - description: findOneAndUpdate
+ runOnRequirements:
+ - minServerVersion: "4.4"
+ operations:
+ - name: findOneAndUpdate
+ object: *collection0
+ arguments:
+ filter: &filter
+ _id: 1
+ update: &update
+ - $set: { x: 5 }
+ comment: "comment"
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: findAndModify operation-find-one-and-update.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-find-one-and-update
+ db.collection.name: test
+ db.operation.name: findAndModify
+ db.operation.summary: findAndModify operation-find-one-and-update.test
+
+ nested:
+ - name: findAndModify
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-find-one-and-update
+ db.collection.name: test
+ db.command.name: findAndModify
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.query.summary: findAndModify operation-find-one-and-update.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ findAndModify: test
+ query: *filter
+ update: *update
+ comment: "comment"
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/find_without_query_text.json b/specifications/open-telemetry/operation/find_without_query_text.json
new file mode 100644
index 00000000000..74e1614bf4f
--- /dev/null
+++ b/specifications/open-telemetry/operation/find_without_query_text.json
@@ -0,0 +1,119 @@
+{
+ "description": "operation find without db.query.text",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": false
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-find"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "operation-find",
+ "documents": []
+ }
+ ],
+ "tests": [
+ {
+ "description": "find an element",
+ "operations": [
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "find operation-find.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-find",
+ "db.collection.name": "test",
+ "db.operation.name": "find",
+ "db.operation.summary": "find operation-find.test"
+ },
+ "nested": [
+ {
+ "name": "find",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-find",
+ "db.collection.name": "test",
+ "db.command.name": "find",
+ "network.transport": "tcp",
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "find operation-find.test",
+ "db.query.text": {
+ "$$exists": false
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/find_without_query_text.yml b/specifications/open-telemetry/operation/find_without_query_text.yml
new file mode 100644
index 00000000000..428537de5d7
--- /dev/null
+++ b/specifications/open-telemetry/operation/find_without_query_text.yml
@@ -0,0 +1,58 @@
+description: operation find without db.query.text
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: false
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-find
+ - collection:
+ id: &collection0 collection0
+ database: database0
+ collectionName: &collection0Name test
+initialData:
+ - collectionName: test
+ databaseName: operation-find
+ documents: []
+tests:
+ - description: find an element
+ operations:
+ - name: find
+ object: *collection0
+ arguments: { filter: { x: 1 } }
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: find operation-find.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-find
+ db.collection.name: test
+ db.operation.name: find
+ db.operation.summary: find operation-find.test
+ nested:
+ - name: find
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-find
+ db.collection.name: test
+ db.command.name: find
+ network.transport: tcp
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [int, long] }
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.summary: find operation-find.test
+ db.query.text: { $$exists: false }
diff --git a/specifications/open-telemetry/operation/insert.json b/specifications/open-telemetry/operation/insert.json
new file mode 100644
index 00000000000..5ab17cf040b
--- /dev/null
+++ b/specifications/open-telemetry/operation/insert.json
@@ -0,0 +1,146 @@
+{
+ "description": "operation insert",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-insert"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "operation-insert",
+ "documents": []
+ }
+ ],
+ "tests": [
+ {
+ "description": "insert one element",
+ "operations": [
+ {
+ "object": "collection0",
+ "name": "insertOne",
+ "arguments": {
+ "document": {
+ "_id": 1
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "insert operation-insert.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-insert",
+ "db.collection.name": "test",
+ "db.operation.name": "insert",
+ "db.operation.summary": "insert operation-insert.test"
+ },
+ "nested": [
+ {
+ "name": "insert",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.command.name": "insert",
+ "db.namespace": "operation-insert",
+ "db.collection.name": "test",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "network.transport": "tcp",
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "insert operation-insert.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "insert": "test",
+ "ordered": true,
+ "txnNumber": {
+ "$$unsetOrMatches": 1
+ },
+ "documents": [
+ {
+ "_id": 1
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "outcome": [
+ {
+ "collectionName": "test",
+ "databaseName": "operation-insert",
+ "documents": [
+ {
+ "_id": 1
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/insert.yml b/specifications/open-telemetry/operation/insert.yml
new file mode 100644
index 00000000000..dbb11fafa26
--- /dev/null
+++ b/specifications/open-telemetry/operation/insert.yml
@@ -0,0 +1,72 @@
+description: operation insert
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-insert
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: test
+initialData:
+ - collectionName: test
+ databaseName: operation-insert
+ documents: [ ]
+tests:
+ - description: insert one element
+ operations:
+ - object: *collection0
+ name: insertOne
+ arguments: { document: { _id: 1 } }
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: insert operation-insert.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-insert
+ db.collection.name: test
+ db.operation.name: insert
+ db.operation.summary: insert operation-insert.test
+ nested:
+ - name: insert
+ attributes:
+ db.system: mongodb
+ db.command.name: insert
+ db.namespace: operation-insert
+ db.collection.name: test
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ network.transport: tcp
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.summary: insert operation-insert.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ insert: test
+ ordered: true
+ txnNumber: { $$unsetOrMatches: 1 }
+ documents:
+ - _id: 1
+
+ outcome:
+ - collectionName: test
+ databaseName: operation-insert
+ documents:
+ - _id: 1
diff --git a/specifications/open-telemetry/operation/list_collections.json b/specifications/open-telemetry/operation/list_collections.json
new file mode 100644
index 00000000000..d9b1937eb50
--- /dev/null
+++ b/specifications/open-telemetry/operation/list_collections.json
@@ -0,0 +1,108 @@
+{
+ "description": "operation list_collections",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-list-collections"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "List collections",
+ "operations": [
+ {
+ "object": "database0",
+ "name": "listCollections"
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "listCollections operation-list-collections",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-list-collections",
+ "db.operation.name": "listCollections",
+ "db.operation.summary": "listCollections operation-list-collections",
+ "db.collection.name": {
+ "$$exists": false
+ }
+ },
+ "nested": [
+ {
+ "name": "listCollections",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-list-collections",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.command.name": "listCollections",
+ "network.transport": "tcp",
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "listCollections operation-list-collections",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "listCollections": 1
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/list_collections.yml b/specifications/open-telemetry/operation/list_collections.yml
new file mode 100644
index 00000000000..da17fbb2e48
--- /dev/null
+++ b/specifications/open-telemetry/operation/list_collections.yml
@@ -0,0 +1,53 @@
+description: operation list_collections
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-list-collections
+tests:
+ - description: List collections
+ operations:
+ - object: *database0
+ name: listCollections
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: listCollections operation-list-collections
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-list-collections
+ db.operation.name: listCollections
+ db.operation.summary: listCollections operation-list-collections
+ db.collection.name: { $$exists: false }
+
+ nested:
+ - name: listCollections
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-list-collections
+ db.collection.name: { $$exists: false }
+ db.command.name: listCollections
+ network.transport: tcp
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.query.summary: listCollections operation-list-collections
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ listCollections: 1
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/list_databases.json b/specifications/open-telemetry/operation/list_databases.json
new file mode 100644
index 00000000000..8fbd8b1014c
--- /dev/null
+++ b/specifications/open-telemetry/operation/list_databases.json
@@ -0,0 +1,104 @@
+{
+ "description": "operation list_databases",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "list databases",
+ "operations": [
+ {
+ "object": "client0",
+ "name": "listDatabases"
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "listDatabases admin",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.operation.name": "listDatabases",
+ "db.operation.summary": "listDatabases admin",
+ "db.collection.name": {
+ "$$exists": false
+ }
+ },
+ "nested": [
+ {
+ "name": "listDatabases",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.command.name": "listDatabases",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "listDatabases admin",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "listDatabases": 1
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/list_databases.yml b/specifications/open-telemetry/operation/list_databases.yml
new file mode 100644
index 00000000000..4adc361af6b
--- /dev/null
+++ b/specifications/open-telemetry/operation/list_databases.yml
@@ -0,0 +1,50 @@
+description: operation list_databases
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+tests:
+ - description: list databases
+ operations:
+ - object: *client0
+ name: listDatabases
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: listDatabases admin
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.operation.name: listDatabases
+ db.operation.summary: listDatabases admin
+ db.collection.name: { $$exists: false }
+
+ nested:
+ - name: listDatabases
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.collection.name: { $$exists: false }
+ db.command.name: listDatabases
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.query.summary: listDatabases admin
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ listDatabases: 1
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/list_indexes.json b/specifications/open-telemetry/operation/list_indexes.json
new file mode 100644
index 00000000000..2674dec2259
--- /dev/null
+++ b/specifications/open-telemetry/operation/list_indexes.json
@@ -0,0 +1,118 @@
+{
+ "description": "operation list_indexes",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-list-indexes"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "operation-list-indexes",
+ "documents": []
+ }
+ ],
+ "tests": [
+ {
+ "description": "List indexes",
+ "operations": [
+ {
+ "object": "collection0",
+ "name": "listIndexes"
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "listIndexes operation-list-indexes.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-list-indexes",
+ "db.collection.name": "test",
+ "db.operation.name": "listIndexes",
+ "db.operation.summary": "listIndexes operation-list-indexes.test"
+ },
+ "nested": [
+ {
+ "name": "listIndexes",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-list-indexes",
+ "db.collection.name": "test",
+ "db.command.name": "listIndexes",
+ "network.transport": "tcp",
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "listIndexes operation-list-indexes.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "listIndexes": "test"
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/list_indexes.yml b/specifications/open-telemetry/operation/list_indexes.yml
new file mode 100644
index 00000000000..28c48e20dcb
--- /dev/null
+++ b/specifications/open-telemetry/operation/list_indexes.yml
@@ -0,0 +1,61 @@
+description: operation list_indexes
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-list-indexes
+ - collection:
+ id: &collection0 collection0
+ database: database0
+ collectionName: test
+initialData:
+ - collectionName: test
+ databaseName: operation-list-indexes
+ documents: [ ]
+tests:
+ - description: List indexes
+ operations:
+ - object: *collection0
+ name: listIndexes
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: listIndexes operation-list-indexes.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-list-indexes
+ db.collection.name: test
+ db.operation.name: listIndexes
+ db.operation.summary: listIndexes operation-list-indexes.test
+
+ nested:
+ - name: listIndexes
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-list-indexes
+ db.collection.name: test
+ db.command.name: listIndexes
+ network.transport: tcp
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.query.summary: listIndexes operation-list-indexes.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ listIndexes: test
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/map_reduce.json b/specifications/open-telemetry/operation/map_reduce.json
new file mode 100644
index 00000000000..fbe0972af7f
--- /dev/null
+++ b/specifications/open-telemetry/operation/map_reduce.json
@@ -0,0 +1,177 @@
+{
+ "description": "operation map_reduce",
+ "schemaVersion": "1.27",
+ "runOnRequirements": [
+ {
+ "minServerVersion": "4.0",
+ "topologies": [
+ "single",
+ "replicaset"
+ ]
+ },
+ {
+ "minServerVersion": "4.1.7",
+ "serverless": "forbid",
+ "topologies": [
+ "sharded",
+ "load-balanced"
+ ]
+ }
+ ],
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-map-reduce"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "operation-map-reduce",
+ "documents": [
+ {
+ "_id": 1,
+ "x": 0
+ },
+ {
+ "_id": 2,
+ "x": 1
+ },
+ {
+ "_id": 3,
+ "x": 2
+ }
+ ]
+ }
+ ],
+ "tests": [
+ {
+ "description": "mapReduce",
+ "operations": [
+ {
+ "object": "collection0",
+ "name": "mapReduce",
+ "arguments": {
+ "map": {
+ "$code": "function inc() { return emit(0, this.x + 1) }"
+ },
+ "reduce": {
+ "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }"
+ },
+ "out": {
+ "inline": 1
+ }
+ },
+ "expectResult": [
+ {
+ "_id": 0,
+ "value": 6
+ }
+ ]
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "mapReduce operation-map-reduce.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-map-reduce",
+ "db.collection.name": "test",
+ "db.operation.name": "mapReduce",
+ "db.operation.summary": "mapReduce operation-map-reduce.test"
+ },
+ "nested": [
+ {
+ "name": "mapReduce",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-map-reduce",
+ "db.collection.name": "test",
+ "db.command.name": "mapReduce",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "mapReduce operation-map-reduce.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "mapReduce": "test",
+ "map": {
+ "$code": "function inc() { return emit(0, this.x + 1) }"
+ },
+ "reduce": {
+ "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }"
+ },
+ "out": {
+ "inline": 1
+ }
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/map_reduce.yml b/specifications/open-telemetry/operation/map_reduce.yml
new file mode 100644
index 00000000000..7fd74bc217a
--- /dev/null
+++ b/specifications/open-telemetry/operation/map_reduce.yml
@@ -0,0 +1,99 @@
+description: operation map_reduce
+schemaVersion: '1.27'
+runOnRequirements:
+ -
+ minServerVersion: '4.0'
+ topologies:
+ - single
+ - replicaset
+ -
+ minServerVersion: 4.1.7
+ # serverless proxy does not support mapReduce operation
+ serverless: forbid
+ topologies:
+ - sharded
+ - load-balanced
+
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: operation-map-reduce
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: test
+initialData:
+ -
+ collectionName: test
+ databaseName: operation-map-reduce
+ documents:
+ -
+ _id: 1
+ x: 0
+ -
+ _id: 2
+ x: 1
+ -
+ _id: 3
+ x: 2
+tests:
+ - description: mapReduce
+ operations:
+ - object: *collection0
+ name: mapReduce
+ arguments:
+ map:
+ $code: 'function inc() { return emit(0, this.x + 1) }'
+ reduce:
+ $code: 'function sum(key, values) { return values.reduce((acc, x) => acc + x); }'
+ out:
+ inline: 1
+ expectResult:
+ -
+ _id: 0
+ value: 6
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: mapReduce operation-map-reduce.test
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-map-reduce
+ db.collection.name: test
+ db.operation.name: mapReduce
+ db.operation.summary: mapReduce operation-map-reduce.test
+
+ nested:
+ - name: mapReduce
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-map-reduce
+ db.collection.name: test
+ db.command.name: mapReduce
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.query.summary: mapReduce operation-map-reduce.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ mapReduce: test
+ map: { $code: 'function inc() { return emit(0, this.x + 1) }' }
+ reduce: { $code: 'function sum(key, values) { return values.reduce((acc, x) => acc + x); }' }
+ out: { inline: 1 }
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/retries.json b/specifications/open-telemetry/operation/retries.json
new file mode 100644
index 00000000000..b8a94547c10
--- /dev/null
+++ b/specifications/open-telemetry/operation/retries.json
@@ -0,0 +1,209 @@
+{
+ "description": "retries",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "client": {
+ "id": "failPointClient",
+ "useMultipleMongoses": false
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-retries"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "operation-retries",
+ "documents": []
+ }
+ ],
+ "tests": [
+ {
+ "description": "find an element with retries",
+ "operations": [
+ {
+ "name": "failPoint",
+ "object": "testRunner",
+ "arguments": {
+ "client": "failPointClient",
+ "failPoint": {
+ "configureFailPoint": "failCommand",
+ "mode": {
+ "times": 1
+ },
+ "data": {
+ "failCommands": [
+ "find"
+ ],
+ "errorCode": 89,
+ "errorLabels": [
+ "RetryableWriteError"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": true,
+ "spans": [
+ {
+ "name": "find operation-retries.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-retries",
+ "db.collection.name": "test",
+ "db.operation.name": "find",
+ "db.operation.summary": "find operation-retries.test"
+ },
+ "nested": [
+ {
+ "name": "find",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-retries",
+ "db.collection.name": "test",
+ "db.command.name": "find",
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": "89",
+ "exception.message": {
+ "$$type": "string"
+ },
+ "exception.type": {
+ "$$type": "string"
+ },
+ "exception.stacktrace": {
+ "$$type": "string"
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.query.summary": "find operation-retries.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "find": "test",
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ },
+ {
+ "name": "find",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-retries",
+ "db.collection.name": "test",
+ "db.command.name": "find",
+ "network.transport": "tcp",
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "find operation-retries.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "find": "test",
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/retries.yml b/specifications/open-telemetry/operation/retries.yml
new file mode 100644
index 00000000000..8375ffb1d64
--- /dev/null
+++ b/specifications/open-telemetry/operation/retries.yml
@@ -0,0 +1,105 @@
+description: retries
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - client:
+ id: &failPointClient failPointClient
+ useMultipleMongoses: false
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: &database0Name operation-retries
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: &collection0Name test
+initialData:
+ - collectionName: test
+ databaseName: operation-retries
+ documents: [ ]
+tests:
+ - description: find an element with retries
+ operations:
+ - name: failPoint
+ object: testRunner
+ arguments:
+ client: *failPointClient
+ failPoint:
+ configureFailPoint: failCommand
+ mode: { times: 1 }
+ data:
+ failCommands: [ find ]
+ errorCode: 89
+ errorLabels: [ RetryableWriteError ]
+
+ - name: find
+ object: *collection0
+ arguments:
+ filter: { x: 1 }
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: true
+ spans:
+ - name: find operation-retries.test
+ attributes:
+ db.system: mongodb
+ db.namespace: *database0Name
+ db.collection.name: *collection0Name
+ db.operation.name: find
+ db.operation.summary: find operation-retries.test
+
+ nested:
+ - name: find
+ attributes:
+ db.system: mongodb
+ db.namespace: *database0Name
+ db.collection.name: *collection0Name
+ db.command.name: find
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: '89'
+ exception.message: { $$type: string }
+ exception.type: { $$type: string }
+ exception.stacktrace: { $$type: string }
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.query.summary: find operation-retries.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ find: test
+ filter:
+ x: 1
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ - name: find
+ attributes:
+ db.system: mongodb
+ db.namespace: *database0Name
+ db.collection.name: *collection0Name
+ db.command.name: find
+ network.transport: tcp
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.query.summary: find operation-retries.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ find: test
+ filter:
+ x: 1
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
diff --git a/specifications/open-telemetry/operation/update.json b/specifications/open-telemetry/operation/update.json
new file mode 100644
index 00000000000..06a6e3fe412
--- /dev/null
+++ b/specifications/open-telemetry/operation/update.json
@@ -0,0 +1,140 @@
+{
+ "description": "operation update",
+ "schemaVersion": "1.27",
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "operation-update"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "description": "update one element",
+ "operations": [
+ {
+ "object": "collection0",
+ "name": "updateOne",
+ "arguments": {
+ "filter": {
+ "_id": 1
+ },
+ "update": {
+ "$inc": {
+ "x": 1
+ }
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "update operation-update.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-update",
+ "db.collection.name": "test",
+ "db.operation.name": "update",
+ "db.operation.summary": "update operation-update.test"
+ },
+ "nested": [
+ {
+ "name": "update",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "operation-update",
+ "db.collection.name": "test",
+ "db.command.name": "update",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "network.transport": "tcp",
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "update operation-update.test",
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "update": "test",
+ "ordered": true,
+ "txnNumber": {
+ "$$unsetOrMatches": 1
+ },
+ "updates": [
+ {
+ "q": {
+ "_id": 1
+ },
+ "u": {
+ "$inc": {
+ "x": 1
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/operation/update.yml b/specifications/open-telemetry/operation/update.yml
new file mode 100644
index 00000000000..c3c816ec17e
--- /dev/null
+++ b/specifications/open-telemetry/operation/update.yml
@@ -0,0 +1,66 @@
+description: operation update
+schemaVersion: '1.27'
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: &databaseName0 operation-update
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: &collectionName0 test
+
+tests:
+ - description: update one element
+ operations:
+ -
+ object: *collection0
+ name: updateOne
+ arguments:
+ filter: { _id: 1 }
+ update: { $inc: { x: 1 } }
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: update operation-update.test
+ attributes:
+ db.system: mongodb
+ db.namespace: *databaseName0
+ db.collection.name: *collectionName0
+ db.operation.name: update
+ db.operation.summary: update operation-update.test
+
+ nested:
+ - name: update
+ attributes:
+ db.system: mongodb
+ db.namespace: operation-update
+ db.collection.name: *collectionName0
+ db.command.name: update
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ network.transport: tcp
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.summary: update operation-update.test
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ update: test
+ ordered: true
+ txnNumber: { $$unsetOrMatches: 1 }
+ updates: [ { "q": { "_id": 1 }, "u": { "$inc": { "x": 1 } } } ]
diff --git a/specifications/open-telemetry/transaction/convenient.json b/specifications/open-telemetry/transaction/convenient.json
new file mode 100644
index 00000000000..b0245151d14
--- /dev/null
+++ b/specifications/open-telemetry/transaction/convenient.json
@@ -0,0 +1,326 @@
+{
+ "description": "convenient transactions",
+ "schemaVersion": "1.27",
+ "runOnRequirements": [
+ {
+ "minServerVersion": "4.4",
+ "topologies": [
+ "replicaset",
+ "sharded"
+ ]
+ }
+ ],
+ "createEntities": [
+ {
+ "client": {
+ "id": "client",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database",
+ "client": "client",
+ "databaseName": "convenient-transaction-tests"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection",
+ "database": "database",
+ "collectionName": "test"
+ }
+ },
+ {
+ "session": {
+ "id": "session",
+ "client": "client"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "convenient-transaction-tests",
+ "documents": []
+ }
+ ],
+ "tests": [
+ {
+ "description": "withTransaction",
+ "operations": [
+ {
+ "name": "withTransaction",
+ "object": "session",
+ "arguments": {
+ "callback": [
+ {
+ "name": "insertOne",
+ "object": "collection",
+ "arguments": {
+ "document": {
+ "_id": 1
+ },
+ "session": "session"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "find",
+ "object": "collection",
+ "arguments": {
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "transaction",
+ "attributes": {
+ "db.system": "mongodb"
+ },
+ "nested": [
+ {
+ "name": "insert convenient-transaction-tests.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "convenient-transaction-tests",
+ "db.collection.name": "test",
+ "db.operation.name": "insert",
+ "db.operation.summary": "insert convenient-transaction-tests.test"
+ },
+ "nested": [
+ {
+ "name": "insert",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "convenient-transaction-tests",
+ "db.collection.name": "test",
+ "db.command.name": "insert",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.query.summary": "insert convenient-transaction-tests.test",
+ "db.mongodb.lsid": {
+ "$$sessionLsid": "session"
+ },
+ "db.mongodb.txn_number": 1,
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "insert": "test",
+ "ordered": true,
+ "txnNumber": 1,
+ "startTransaction": true,
+ "autocommit": false,
+ "documents": [
+ {
+ "_id": 1
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "commitTransaction admin",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.operation.name": "commitTransaction",
+ "db.operation.summary": "commitTransaction admin"
+ },
+ "nested": [
+ {
+ "name": "commitTransaction",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.query.summary": "commitTransaction admin",
+ "db.command.name": "commitTransaction",
+ "db.mongodb.lsid": {
+ "$$sessionLsid": "session"
+ },
+ "db.mongodb.txn_number": 1,
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "network.transport": "tcp",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "commitTransaction": 1,
+ "txnNumber": 1,
+ "autocommit": false
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "find convenient-transaction-tests.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "convenient-transaction-tests",
+ "db.collection.name": "test",
+ "db.operation.summary": "find convenient-transaction-tests.test",
+ "db.operation.name": "find"
+ },
+ "nested": [
+ {
+ "name": "find",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "convenient-transaction-tests",
+ "db.collection.name": "test",
+ "db.command.name": "find",
+ "network.transport": "tcp",
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.summary": "find convenient-transaction-tests.test",
+ "db.query.text": {
+ "$$exists": true
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "outcome": [
+ {
+ "collectionName": "test",
+ "databaseName": "convenient-transaction-tests",
+ "documents": [
+ {
+ "_id": 1
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/transaction/convenient.yml b/specifications/open-telemetry/transaction/convenient.yml
new file mode 100644
index 00000000000..a606b82957c
--- /dev/null
+++ b/specifications/open-telemetry/transaction/convenient.yml
@@ -0,0 +1,167 @@
+description: convenient transactions
+
+schemaVersion: "1.27"
+
+runOnRequirements:
+ - minServerVersion: "4.4"
+ topologies: ["replicaset", "sharded"]
+
+createEntities:
+ - client:
+ id: &client client
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database database
+ client: *client
+ databaseName: &databaseName convenient-transaction-tests
+ - collection:
+ id: &collection collection
+ database: *database
+ collectionName: &collectionName test
+ - session:
+ id: &session session
+ client: *client
+
+initialData:
+ - collectionName: *collectionName
+ databaseName: *databaseName
+ documents: []
+
+tests:
+ - description: "withTransaction"
+ operations:
+ - name: withTransaction
+ object: *session
+ arguments:
+ callback:
+ - name: insertOne
+ object: *collection
+ arguments:
+ document:
+ _id: 1
+ session: *session
+ - name: find
+ object: *collection
+ arguments: { filter: { x: 1 } }
+
+ expectTracingMessages:
+ - client: *client
+ ignoreExtraSpans: false
+ spans:
+ - name: transaction
+ attributes:
+ db.system: mongodb
+ nested:
+ - name: insert convenient-transaction-tests.test
+ attributes:
+ db.system: mongodb
+ db.namespace: *databaseName
+ db.collection.name: *collectionName
+ db.operation.name: insert
+ db.operation.summary: insert convenient-transaction-tests.test
+
+ nested:
+ - name: insert
+ attributes:
+ db.system: mongodb
+ db.namespace: *databaseName
+ db.collection.name: *collectionName
+ db.command.name: insert
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.query.summary: insert convenient-transaction-tests.test
+ db.mongodb.lsid: { $$sessionLsid: *session }
+ db.mongodb.txn_number: 1
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ insert: test
+ ordered: true
+ txnNumber: 1
+ startTransaction: true
+ autocommit: false
+ documents:
+ - _id: 1
+ - name: commitTransaction admin
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.collection.name: { $$exists: false }
+ db.operation.name: commitTransaction
+ db.operation.summary: commitTransaction admin
+
+ nested:
+ - name: commitTransaction
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.collection.name: { $$exists: false }
+ db.query.summary: commitTransaction admin
+ db.command.name: commitTransaction
+ db.mongodb.lsid: { $$sessionLsid: *session }
+ db.mongodb.txn_number: 1
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ network.transport: tcp
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ commitTransaction: 1
+ txnNumber: 1
+ autocommit: false
+
+ - name: find convenient-transaction-tests.test
+ attributes:
+ db.system: mongodb
+ db.namespace: *databaseName
+ db.collection.name: *collectionName
+ db.operation.summary: find convenient-transaction-tests.test
+ db.operation.name: find
+
+ nested:
+ - name: find
+ attributes:
+ db.system: mongodb
+ db.namespace: *databaseName
+ db.collection.name: *collectionName
+ db.command.name: find
+ network.transport: tcp
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ server.address: { $$type: string }
+ server.port: { $$type: [ long, string ] }
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.summary: find convenient-transaction-tests.test
+ db.query.text: { $$exists: true }
+
+ outcome:
+ - collectionName: test
+ databaseName: convenient-transaction-tests
+ documents:
+ - _id: 1
diff --git a/specifications/open-telemetry/transaction/core_api.json b/specifications/open-telemetry/transaction/core_api.json
new file mode 100644
index 00000000000..93e3a9933d1
--- /dev/null
+++ b/specifications/open-telemetry/transaction/core_api.json
@@ -0,0 +1,545 @@
+{
+ "description": "transaction spans",
+ "schemaVersion": "1.27",
+ "runOnRequirements": [
+ {
+ "minServerVersion": "4.0",
+ "topologies": [
+ "replicaset"
+ ]
+ },
+ {
+ "minServerVersion": "4.1.8",
+ "topologies": [
+ "sharded",
+ "load-balanced"
+ ]
+ }
+ ],
+ "createEntities": [
+ {
+ "client": {
+ "id": "client0",
+ "useMultipleMongoses": false,
+ "observeTracingMessages": {
+ "enableCommandPayload": true
+ }
+ }
+ },
+ {
+ "database": {
+ "id": "database0",
+ "client": "client0",
+ "databaseName": "transaction-tests"
+ }
+ },
+ {
+ "collection": {
+ "id": "collection0",
+ "database": "database0",
+ "collectionName": "test"
+ }
+ },
+ {
+ "session": {
+ "id": "session0",
+ "client": "client0"
+ }
+ }
+ ],
+ "initialData": [
+ {
+ "collectionName": "test",
+ "databaseName": "transaction-tests",
+ "documents": []
+ }
+ ],
+ "tests": [
+ {
+ "description": "commit transaction",
+ "operations": [
+ {
+ "object": "session0",
+ "name": "startTransaction"
+ },
+ {
+ "object": "collection0",
+ "name": "insertOne",
+ "arguments": {
+ "session": "session0",
+ "document": {
+ "_id": 1
+ }
+ }
+ },
+ {
+ "object": "session0",
+ "name": "commitTransaction"
+ },
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "filter": {
+ "x": 1
+ }
+ }
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "transaction",
+ "attributes": {
+ "db.system": "mongodb"
+ },
+ "nested": [
+ {
+ "name": "insert transaction-tests.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "transaction-tests",
+ "db.collection.name": "test",
+ "db.operation.name": "insert",
+ "db.operation.summary": "insert transaction-tests.test"
+ },
+ "nested": [
+ {
+ "name": "insert",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "transaction-tests",
+ "db.collection.name": "test",
+ "db.command.name": "insert",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.query.summary": "insert transaction-tests.test",
+ "db.mongodb.lsid": {
+ "$$sessionLsid": "session0"
+ },
+ "db.mongodb.txn_number": 1,
+ "network.transport": "tcp",
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "insert": "test",
+ "ordered": true,
+ "txnNumber": 1,
+ "startTransaction": true,
+ "autocommit": false,
+ "documents": [
+ {
+ "_id": 1
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "commitTransaction admin",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.operation.name": "commitTransaction",
+ "db.operation.summary": "commitTransaction admin"
+ },
+ "nested": [
+ {
+ "name": "commitTransaction",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.query.summary": "commitTransaction admin",
+ "db.command.name": "commitTransaction",
+ "db.mongodb.lsid": {
+ "$$sessionLsid": "session0"
+ },
+ "db.mongodb.txn_number": 1,
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "network.transport": "tcp",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "commitTransaction": 1,
+ "txnNumber": 1,
+ "autocommit": false
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "find transaction-tests.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "transaction-tests",
+ "db.collection.name": "test",
+ "db.operation.summary": "find transaction-tests.test",
+ "db.operation.name": "find"
+ },
+ "nested": [
+ {
+ "name": "find",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "transaction-tests",
+ "db.collection.name": "test",
+ "db.command.name": "find",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "network.transport": "tcp",
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.text": {
+ "$$exists": true
+ },
+ "db.query.summary": "find transaction-tests.test"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "outcome": [
+ {
+ "collectionName": "test",
+ "databaseName": "transaction-tests",
+ "documents": [
+ {
+ "_id": 1
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "description": "abort transaction",
+ "operations": [
+ {
+ "object": "session0",
+ "name": "startTransaction"
+ },
+ {
+ "object": "collection0",
+ "name": "insertOne",
+ "arguments": {
+ "session": "session0",
+ "document": {
+ "_id": 1
+ }
+ }
+ },
+ {
+ "object": "session0",
+ "name": "abortTransaction"
+ }
+ ],
+ "expectTracingMessages": [
+ {
+ "client": "client0",
+ "ignoreExtraSpans": false,
+ "spans": [
+ {
+ "name": "transaction",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": {
+ "$$exists": false
+ },
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.operation.name": {
+ "$$exists": false
+ },
+ "db.operation.summary": {
+ "$$exists": false
+ }
+ },
+ "nested": [
+ {
+ "name": "insert transaction-tests.test",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "transaction-tests",
+ "db.collection.name": "test",
+ "db.operation.name": "insert",
+ "db.operation.summary": "insert transaction-tests.test"
+ },
+ "nested": [
+ {
+ "name": "insert",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "transaction-tests",
+ "db.collection.name": "test",
+ "db.command.name": "insert",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "long",
+ "string"
+ ]
+ },
+ "db.query.summary": "insert transaction-tests.test",
+ "db.mongodb.lsid": {
+ "$$sessionLsid": "session0"
+ },
+ "db.mongodb.txn_number": 1,
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "network.transport": "tcp",
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "insert": "test",
+ "ordered": true,
+ "txnNumber": 1,
+ "startTransaction": true,
+ "autocommit": false,
+ "documents": [
+ {
+ "_id": 1
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "abortTransaction admin",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.operation.name": "abortTransaction",
+ "db.operation.summary": "abortTransaction admin"
+ },
+ "nested": [
+ {
+ "name": "abortTransaction",
+ "attributes": {
+ "db.system": "mongodb",
+ "db.namespace": "admin",
+ "db.collection.name": {
+ "$$exists": false
+ },
+ "db.query.summary": "abortTransaction admin",
+ "db.command.name": "abortTransaction",
+ "db.mongodb.lsid": {
+ "$$sessionLsid": "session0"
+ },
+ "db.mongodb.txn_number": 1,
+ "db.mongodb.cursor_id": {
+ "$$exists": false
+ },
+ "db.response.status_code": {
+ "$$exists": false
+ },
+ "exception.message": {
+ "$$exists": false
+ },
+ "exception.type": {
+ "$$exists": false
+ },
+ "exception.stacktrace": {
+ "$$exists": false
+ },
+ "network.transport": "tcp",
+ "server.address": {
+ "$$type": "string"
+ },
+ "server.port": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.server_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.mongodb.driver_connection_id": {
+ "$$type": [
+ "int",
+ "long"
+ ]
+ },
+ "db.query.text": {
+ "$$matchAsDocument": {
+ "$$matchAsRoot": {
+ "abortTransaction": 1,
+ "txnNumber": 1,
+ "autocommit": false
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "outcome": [
+ {
+ "collectionName": "test",
+ "databaseName": "transaction-tests",
+ "documents": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/specifications/open-telemetry/transaction/core_api.yml b/specifications/open-telemetry/transaction/core_api.yml
new file mode 100644
index 00000000000..fe10899ed0d
--- /dev/null
+++ b/specifications/open-telemetry/transaction/core_api.yml
@@ -0,0 +1,269 @@
+description: transaction spans
+schemaVersion: '1.27'
+runOnRequirements:
+ - minServerVersion: '4.0'
+ topologies:
+ - replicaset
+ - minServerVersion: '4.1.8'
+ topologies:
+ - sharded
+ - load-balanced
+createEntities:
+ - client:
+ id: &client0 client0
+ useMultipleMongoses: false
+ observeTracingMessages:
+ enableCommandPayload: true
+ - database:
+ id: &database0 database0
+ client: *client0
+ databaseName: transaction-tests
+ - collection:
+ id: &collection0 collection0
+ database: *database0
+ collectionName: test
+ - session:
+ id: &session0 session0
+ client: client0
+initialData:
+ - collectionName: test
+ databaseName: transaction-tests
+ documents: []
+tests:
+ - description: commit transaction
+ operations:
+ - object: *session0
+ name: startTransaction
+ - object: *collection0
+ name: insertOne
+ arguments:
+ session: *session0
+ document:
+ _id: 1
+ - object: *session0
+ name: commitTransaction
+ - name: find
+ object: *collection0
+ arguments: { filter: { x: 1 } }
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: transaction
+ attributes:
+ db.system: mongodb
+ nested:
+ - name: insert transaction-tests.test
+ attributes:
+ db.system: mongodb
+ db.namespace: transaction-tests
+ db.collection.name: test
+ db.operation.name: insert
+ db.operation.summary: insert transaction-tests.test
+
+ nested:
+ - name: insert
+ attributes:
+ db.system: mongodb
+ db.namespace: transaction-tests
+ db.collection.name: test
+ db.command.name: insert
+ server.address: { $$type: string }
+ server.port: { $$type: [long, string] }
+ db.query.summary: insert transaction-tests.test
+ db.mongodb.lsid: { $$sessionLsid: *session0 }
+ db.mongodb.txn_number: 1
+ network.transport: tcp
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ insert: test
+ ordered: true
+ txnNumber: 1
+ startTransaction: true
+ autocommit: false
+ documents:
+ - _id: 1
+ - name: commitTransaction admin
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.collection.name: { $$exists: false }
+ db.operation.name: commitTransaction
+ db.operation.summary: commitTransaction admin
+
+ nested:
+ - name: commitTransaction
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.collection.name: { $$exists: false }
+ db.query.summary: commitTransaction admin
+ db.command.name: commitTransaction
+ db.mongodb.lsid: { $$sessionLsid: *session0 }
+ db.mongodb.txn_number: 1
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ network.transport: tcp
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ commitTransaction: 1
+ txnNumber: 1
+ autocommit: false
+ - name: find transaction-tests.test
+ attributes:
+ db.system: mongodb
+ db.namespace: transaction-tests
+ db.collection.name: test
+ db.operation.summary: find transaction-tests.test
+ db.operation.name: find
+ nested:
+ - name: find
+ attributes:
+ db.system: mongodb
+ db.namespace: transaction-tests
+ db.collection.name: test
+ db.command.name: find
+ server.address: { $$type: string }
+ server.port: { $$type: [long, string] }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ network.transport: tcp
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.text: { $$exists: true }
+ db.query.summary: find transaction-tests.test
+ outcome:
+ - collectionName: test
+ databaseName: transaction-tests
+ documents:
+ - _id: 1
+
+ - description: abort transaction
+ operations:
+ - object: *session0
+ name: startTransaction
+ - object: *collection0
+ name: insertOne
+ arguments:
+ session: *session0
+ document:
+ _id: 1
+ - object: *session0
+ name: abortTransaction
+
+ expectTracingMessages:
+ - client: *client0
+ ignoreExtraSpans: false
+ spans:
+ - name: transaction
+ attributes:
+ db.system: mongodb
+ db.namespace: { $$exists: false }
+ db.collection.name: { $$exists: false }
+ db.operation.name: { $$exists: false }
+ db.operation.summary: { $$exists: false }
+ nested:
+ - name: insert transaction-tests.test
+ attributes:
+ db.system: mongodb
+ db.namespace: transaction-tests
+ db.collection.name: test
+ db.operation.name: insert
+ db.operation.summary: insert transaction-tests.test
+ nested:
+ - name: insert
+ attributes:
+ db.system: mongodb
+ db.namespace: transaction-tests
+ db.collection.name: test
+ db.command.name: insert
+ server.address: { $$type: string }
+ server.port: { $$type: [long, string] }
+ db.query.summary: insert transaction-tests.test
+ db.mongodb.lsid: { $$sessionLsid: *session0 }
+ db.mongodb.txn_number: 1
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ network.transport: tcp
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ insert: test
+ ordered: true
+ txnNumber: 1
+ startTransaction: true
+ autocommit: false
+ documents:
+ - _id: 1
+ - name: abortTransaction admin
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.collection.name: { $$exists: false }
+ db.operation.name: abortTransaction
+ db.operation.summary: abortTransaction admin
+ nested:
+ - name: abortTransaction
+ attributes:
+ db.system: mongodb
+ db.namespace: admin
+ db.collection.name: { $$exists: false }
+ db.query.summary: abortTransaction admin
+ db.command.name: abortTransaction
+ db.mongodb.lsid: { $$sessionLsid: *session0 }
+ db.mongodb.txn_number: 1
+ db.mongodb.cursor_id: { $$exists: false }
+ db.response.status_code: { $$exists: false }
+ exception.message: { $$exists: false }
+ exception.type: { $$exists: false }
+ exception.stacktrace: { $$exists: false }
+ network.transport: tcp
+ server.address: { $$type: string }
+ server.port: { $$type: [ int, long ] }
+ db.mongodb.server_connection_id:
+ $$type: [ int, long ]
+ db.mongodb.driver_connection_id:
+ $$type: [ int, long ]
+ db.query.text:
+ $$matchAsDocument:
+ $$matchAsRoot:
+ abortTransaction: 1
+ txnNumber: 1
+ autocommit: false
+
+ outcome:
+ - collectionName: test
+ databaseName: transaction-tests
+ documents: []
diff --git a/src/MongoDB.Driver/ClientSessionHandle.cs b/src/MongoDB.Driver/ClientSessionHandle.cs
index 144e6a94991..a662ce92c2d 100644
--- a/src/MongoDB.Driver/ClientSessionHandle.cs
+++ b/src/MongoDB.Driver/ClientSessionHandle.cs
@@ -158,7 +158,12 @@ public IClientSessionHandle Fork()
public void StartTransaction(TransactionOptions transactionOptions = null)
{
var effectiveTransactionOptions = GetEffectiveTransactionOptions(transactionOptions);
- _coreSession.StartTransaction(effectiveTransactionOptions);
+
+ // Check if tracing is enabled for this client
+ var tracingOptions = _client?.Settings?.TracingOptions;
+ var isTracingEnabled = tracingOptions == null || !tracingOptions.Disabled;
+
+ ((ICoreSessionInternal)_coreSession).StartTransaction(effectiveTransactionOptions, isTracingEnabled);
}
///
diff --git a/src/MongoDB.Driver/ClusterKey.cs b/src/MongoDB.Driver/ClusterKey.cs
index dec3b93bad6..60eca94d396 100644
--- a/src/MongoDB.Driver/ClusterKey.cs
+++ b/src/MongoDB.Driver/ClusterKey.cs
@@ -42,6 +42,7 @@ internal sealed class ClusterKey
private readonly bool _loadBalanced;
private readonly TimeSpan _localThreshold;
private readonly LoggingSettings _loggingSettings;
+ private readonly TracingOptions _tracingOptions;
private readonly int _maxConnecting;
private readonly TimeSpan _maxConnectionIdleTime;
private readonly TimeSpan _maxConnectionLifeTime;
@@ -81,6 +82,7 @@ public ClusterKey(
bool loadBalanced,
TimeSpan localThreshold,
LoggingSettings loggingSettings,
+ TracingOptions tracingOptions,
int maxConnecting,
TimeSpan maxConnectionIdleTime,
TimeSpan maxConnectionLifeTime,
@@ -118,6 +120,7 @@ public ClusterKey(
_loadBalanced = loadBalanced;
_localThreshold = localThreshold;
_loggingSettings = loggingSettings;
+ _tracingOptions = tracingOptions;
_maxConnecting = maxConnecting;
_maxConnectionIdleTime = maxConnectionIdleTime;
_maxConnectionLifeTime = maxConnectionLifeTime;
@@ -159,6 +162,7 @@ public ClusterKey(
public bool LoadBalanced => _loadBalanced;
public TimeSpan LocalThreshold { get { return _localThreshold; } }
public LoggingSettings LoggingSettings { get { return _loggingSettings; } }
+ public TracingOptions TracingOptions { get { return _tracingOptions; } }
public int MaxConnecting{ get { return _maxConnecting; } }
public TimeSpan MaxConnectionIdleTime { get { return _maxConnectionIdleTime; } }
public TimeSpan MaxConnectionLifeTime { get { return _maxConnectionLifeTime; } }
diff --git a/src/MongoDB.Driver/ClusterRegistry.cs b/src/MongoDB.Driver/ClusterRegistry.cs
index 49e599be8d1..60abf4c85d5 100644
--- a/src/MongoDB.Driver/ClusterRegistry.cs
+++ b/src/MongoDB.Driver/ClusterRegistry.cs
@@ -62,7 +62,8 @@ private IClusterInternal CreateCluster(ClusterKey clusterKey)
.ConfigureConnectionPool(settings => ConfigureConnectionPool(settings, clusterKey))
.ConfigureConnection(settings => ConfigureConnection(settings, clusterKey))
.ConfigureTcp(settings => ConfigureTcp(settings, clusterKey))
- .ConfigureLoggingSettings(_ => clusterKey.LoggingSettings);
+ .ConfigureLoggingSettings(_ => clusterKey.LoggingSettings)
+ .ConfigureTracingOptions(_ => clusterKey.TracingOptions);
#pragma warning restore CS0618 // Type or member is obsolete
if (clusterKey.UseTls)
diff --git a/src/MongoDB.Driver/Core/Bindings/CoreSession.cs b/src/MongoDB.Driver/Core/Bindings/CoreSession.cs
index 954c639e244..15a3ab9735c 100644
--- a/src/MongoDB.Driver/Core/Bindings/CoreSession.cs
+++ b/src/MongoDB.Driver/Core/Bindings/CoreSession.cs
@@ -14,10 +14,12 @@
*/
using System;
+using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Bson;
+using MongoDB.Driver;
using MongoDB.Driver.Core.Clusters;
using MongoDB.Driver.Core.Misc;
using MongoDB.Driver.Core.Operations;
@@ -190,6 +192,20 @@ void ICoreSessionInternal.AbortTransaction(AbortTransactionOptions options, Canc
_currentTransaction.SetState(CoreTransactionState.Aborted);
// The transaction is aborted.The session MUST be unpinned regardless
// of whether the abortTransaction command succeeds or fails
+ if (_currentTransaction.TransactionActivity != null)
+ {
+ var transactionActivity = _currentTransaction.TransactionActivity;
+ _currentTransaction.TransactionActivity = null;
+
+ // Set status to Ok for successfully aborted transaction
+ transactionActivity.SetStatus(ActivityStatusCode.Ok);
+
+ // Dispose the transaction activity. Note: Activity.Current was already restored to the
+ // parent in StartTransaction() to prevent AsyncLocal flow issues, so the transaction
+ // activity was never persisted in Activity.Current. Set it explicitly to be defensive.
+ Activity.Current = _currentTransaction.ParentActivity;
+ transactionActivity.Dispose();
+ }
_currentTransaction.UnpinAll();
}
}
@@ -244,6 +260,20 @@ async Task ICoreSessionInternal.AbortTransactionAsync(AbortTransactionOptions op
_currentTransaction.SetState(CoreTransactionState.Aborted);
// The transaction is aborted.The session MUST be unpinned regardless
// of whether the abortTransaction command succeeds or fails
+ if (_currentTransaction.TransactionActivity != null)
+ {
+ var transactionActivity = _currentTransaction.TransactionActivity;
+ _currentTransaction.TransactionActivity = null;
+
+ // Set status to Ok for successfully aborted transaction
+ transactionActivity.SetStatus(ActivityStatusCode.Ok);
+
+ // Dispose the transaction activity. Note: Activity.Current was already restored to the
+ // parent in StartTransaction() to prevent AsyncLocal flow issues, so the transaction
+ // activity was never persisted in Activity.Current. Set it explicitly to be defensive.
+ Activity.Current = _currentTransaction.ParentActivity;
+ transactionActivity.Dispose();
+ }
_currentTransaction.UnpinAll();
}
}
@@ -334,6 +364,21 @@ void ICoreSessionInternal.CommitTransaction(CommitTransactionOptions options, Ca
{
_isCommitTransactionInProgress = false;
_currentTransaction.SetState(CoreTransactionState.Committed);
+ // Stop the transaction span immediately so it's captured for testing
+ if (_currentTransaction.TransactionActivity != null)
+ {
+ var transactionActivity = _currentTransaction.TransactionActivity;
+ _currentTransaction.TransactionActivity = null;
+
+ // Set status to Ok for successfully committed transaction
+ transactionActivity.SetStatus(ActivityStatusCode.Ok);
+
+ // Dispose the transaction activity. Note: Activity.Current was already restored to the
+ // parent in StartTransaction() to prevent AsyncLocal flow issues, so the transaction
+ // activity was never persisted in Activity.Current. Set it explicitly to be defensive.
+ Activity.Current = _currentTransaction.ParentActivity;
+ transactionActivity.Dispose();
+ }
}
}
@@ -374,6 +419,21 @@ async Task ICoreSessionInternal.CommitTransactionAsync(CommitTransactionOptions
{
_isCommitTransactionInProgress = false;
_currentTransaction.SetState(CoreTransactionState.Committed);
+ // Stop the transaction span immediately so it's captured for testing
+ if (_currentTransaction.TransactionActivity != null)
+ {
+ var transactionActivity = _currentTransaction.TransactionActivity;
+ _currentTransaction.TransactionActivity = null;
+
+ // Set status to Ok for successfully committed transaction
+ transactionActivity.SetStatus(ActivityStatusCode.Ok);
+
+ // Dispose the transaction activity. Note: Activity.Current was already restored to the
+ // parent in StartTransaction() to prevent AsyncLocal flow issues, so the transaction
+ // activity was never persisted in Activity.Current. Set it explicitly to be defensive.
+ Activity.Current = _currentTransaction.ParentActivity;
+ transactionActivity.Dispose();
+ }
}
}
@@ -414,6 +474,9 @@ public void MarkDirty()
///
public void StartTransaction(TransactionOptions transactionOptions = null)
+ => ((ICoreSessionInternal)this).StartTransaction(transactionOptions, isTracingEnabled: false);
+
+ void ICoreSessionInternal.StartTransaction(TransactionOptions transactionOptions, bool isTracingEnabled)
{
EnsureStartTransactionCanBeCalled();
@@ -425,7 +488,19 @@ public void StartTransaction(TransactionOptions transactionOptions = null)
}
_currentTransaction?.UnpinAll(); // unpin data if any when a new transaction is started
- _currentTransaction = new CoreTransaction(transactionNumber, effectiveTransactionOptions);
+ _currentTransaction = new CoreTransaction(transactionNumber, effectiveTransactionOptions, isTracingEnabled);
+
+ // Start transaction span for OpenTelemetry tracing (if enabled)
+ if (isTracingEnabled)
+ {
+ // Store the parent activity to restore later
+ _currentTransaction.ParentActivity = Activity.Current;
+ _currentTransaction.TransactionActivity = MongoTelemetry.StartTransactionActivity();
+
+ // Immediately restore Activity.Current to the parent to prevent AsyncLocal flow issues.
+ // The transaction activity will be explicitly set as parent for operations within the transaction.
+ Activity.Current = _currentTransaction.ParentActivity;
+ }
}
///
@@ -559,19 +634,87 @@ private void EnsureTransactionsAreSupported()
private TResult ExecuteEndTransactionOnPrimary(OperationContext operationContext, IReadOperation operation)
{
- using (var sessionHandle = new NonDisposingCoreSessionHandle(this))
- using (var binding = ChannelPinningHelper.CreateReadWriteBinding(_cluster, sessionHandle))
+ // Determine operation name and create operation-level span if tracing is enabled
+ string operationName = operation switch
+ {
+ CommitTransactionOperation => "commitTransaction",
+ AbortTransactionOperation => "abortTransaction",
+ _ => null
+ };
+
+ // Temporarily set Activity.Current to transaction activity so the operation nests under it
+ var transactionActivity = _currentTransaction?.TransactionActivity;
+ var previousActivity = Activity.Current;
+ if (transactionActivity != null)
{
- return operation.Execute(operationContext, binding);
+ Activity.Current = transactionActivity;
+ }
+
+ using var activity = _currentTransaction?.IsTracingEnabled == true && operationName != null
+ ? MongoTelemetry.StartOperationActivity(operationName, "admin", collectionName: null)
+ : null;
+
+ // Don't restore Activity.Current yet - let it stay as the operation activity
+ // so command activities nest under it. We'll restore after the operation completes.
+
+ try
+ {
+ using (var sessionHandle = new NonDisposingCoreSessionHandle(this))
+ using (var binding = ChannelPinningHelper.CreateReadWriteBinding(_cluster, sessionHandle))
+ {
+ return operation.Execute(operationContext, binding);
+ }
+ }
+ finally
+ {
+ // Restore Activity.Current after operation completes
+ if (transactionActivity != null)
+ {
+ Activity.Current = previousActivity;
+ }
}
}
private async Task ExecuteEndTransactionOnPrimaryAsync(OperationContext operationContext, IReadOperation operation)
{
- using (var sessionHandle = new NonDisposingCoreSessionHandle(this))
- using (var binding = ChannelPinningHelper.CreateReadWriteBinding(_cluster, sessionHandle))
+ // Determine operation name and create operation-level span if tracing is enabled
+ string operationName = operation switch
+ {
+ CommitTransactionOperation => "commitTransaction",
+ AbortTransactionOperation => "abortTransaction",
+ _ => null
+ };
+
+ // Temporarily set Activity.Current to transaction activity so the operation nests under it
+ var transactionActivity = _currentTransaction?.TransactionActivity;
+ var previousActivity = Activity.Current;
+ if (transactionActivity != null)
+ {
+ Activity.Current = transactionActivity;
+ }
+
+ using var activity = _currentTransaction?.IsTracingEnabled == true && operationName != null
+ ? MongoTelemetry.StartOperationActivity(operationName, "admin", collectionName: null)
+ : null;
+
+ // Don't restore Activity.Current yet - let it stay as the operation activity
+ // so command activities nest under it. We'll restore after the operation completes.
+
+ try
+ {
+ using (var sessionHandle = new NonDisposingCoreSessionHandle(this))
+ using (var binding = ChannelPinningHelper.CreateReadWriteBinding(_cluster, sessionHandle))
+ {
+ return await operation.ExecuteAsync(operationContext, binding).ConfigureAwait(false);
+ }
+ }
+ finally
{
- return await operation.ExecuteAsync(operationContext, binding).ConfigureAwait(false);
+ // Restore Activity.Current after operation completes
+ if (transactionActivity != null)
+ {
+ Activity.Current = previousActivity;
+ }
}
}
diff --git a/src/MongoDB.Driver/Core/Bindings/CoreTransaction.cs b/src/MongoDB.Driver/Core/Bindings/CoreTransaction.cs
index 6ed2a4f849e..e152702d75e 100644
--- a/src/MongoDB.Driver/Core/Bindings/CoreTransaction.cs
+++ b/src/MongoDB.Driver/Core/Bindings/CoreTransaction.cs
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+using System.Diagnostics;
using MongoDB.Bson;
using MongoDB.Driver.Core.Servers;
@@ -32,6 +33,9 @@ public class CoreTransaction
private readonly long _transactionNumber;
private readonly TransactionOptions _transactionOptions;
private readonly object _lock = new object();
+ private Activity _transactionActivity;
+ private Activity _parentActivity;
+ private readonly bool _isTracingEnabled;
// public constructors
///
@@ -40,9 +44,21 @@ public class CoreTransaction
/// The transaction number.
/// The transaction options.
public CoreTransaction(long transactionNumber, TransactionOptions transactionOptions)
+ : this(transactionNumber, transactionOptions, isTracingEnabled: false)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The transaction number.
+ /// The transaction options.
+ /// Whether OpenTelemetry tracing is enabled for this transaction.
+ internal CoreTransaction(long transactionNumber, TransactionOptions transactionOptions, bool isTracingEnabled)
{
_transactionNumber = transactionNumber;
_transactionOptions = transactionOptions;
+ _isTracingEnabled = isTracingEnabled;
_state = CoreTransactionState.Starting;
_isEmpty = true;
}
@@ -58,6 +74,29 @@ public CoreTransaction(long transactionNumber, TransactionOptions transactionOpt
internal OperationContext OperationContext { get; set; }
+ ///
+ /// Gets or sets the transaction activity (for OpenTelemetry tracing).
+ ///
+ internal Activity TransactionActivity
+ {
+ get => _transactionActivity;
+ set => _transactionActivity = value;
+ }
+
+ ///
+ /// Gets or sets the parent activity to restore after the transaction completes.
+ ///
+ internal Activity ParentActivity
+ {
+ get => _parentActivity;
+ set => _parentActivity = value;
+ }
+
+ ///
+ /// Gets whether OpenTelemetry tracing is enabled for this transaction.
+ ///
+ internal bool IsTracingEnabled => _isTracingEnabled;
+
///
/// Gets the transaction state.
///
@@ -138,6 +177,8 @@ internal void UnpinAll()
_pinnedChannel?.Dispose();
_pinnedChannel = null;
_pinnedServer = null;
+ _transactionActivity?.Dispose();
+ _transactionActivity = null;
}
}
}
diff --git a/src/MongoDB.Driver/Core/Bindings/ICoreSessionInternal.cs b/src/MongoDB.Driver/Core/Bindings/ICoreSessionInternal.cs
index 1844ae6fa8c..c8d84131911 100644
--- a/src/MongoDB.Driver/Core/Bindings/ICoreSessionInternal.cs
+++ b/src/MongoDB.Driver/Core/Bindings/ICoreSessionInternal.cs
@@ -25,4 +25,5 @@ internal interface ICoreSessionInternal
Task AbortTransactionAsync(AbortTransactionOptions options, CancellationToken cancellationToken = default);
void CommitTransaction(CommitTransactionOptions options, CancellationToken cancellationToken = default);
Task CommitTransactionAsync(CommitTransactionOptions options, CancellationToken cancellationToken = default);
+ void StartTransaction(TransactionOptions transactionOptions, bool isTracingEnabled);
}
diff --git a/src/MongoDB.Driver/Core/Bindings/NoCoreSession.cs b/src/MongoDB.Driver/Core/Bindings/NoCoreSession.cs
index ac7e68abf06..52a8d361820 100644
--- a/src/MongoDB.Driver/Core/Bindings/NoCoreSession.cs
+++ b/src/MongoDB.Driver/Core/Bindings/NoCoreSession.cs
@@ -173,6 +173,11 @@ public void StartTransaction(TransactionOptions transactionOptions = null)
throw new NotSupportedException("NoCoreSession does not support StartTransaction.");
}
+ void ICoreSessionInternal.StartTransaction(TransactionOptions transactionOptions, bool isTracingEnabled)
+ {
+ throw new NotSupportedException("NoCoreSession does not support StartTransaction.");
+ }
+
///
public void SetSnapshotTimeIfNeeded(BsonTimestamp snapshotTime)
{
diff --git a/src/MongoDB.Driver/Core/Bindings/WrappingCoreSession.cs b/src/MongoDB.Driver/Core/Bindings/WrappingCoreSession.cs
index 1d61b552d9d..82c2e1288bd 100644
--- a/src/MongoDB.Driver/Core/Bindings/WrappingCoreSession.cs
+++ b/src/MongoDB.Driver/Core/Bindings/WrappingCoreSession.cs
@@ -286,6 +286,12 @@ public virtual void StartTransaction(TransactionOptions transactionOptions = nul
_wrapped.StartTransaction(transactionOptions);
}
+ void ICoreSessionInternal.StartTransaction(TransactionOptions transactionOptions, bool isTracingEnabled)
+ {
+ ThrowIfDisposed();
+ ((ICoreSessionInternal)_wrapped).StartTransaction(transactionOptions, isTracingEnabled);
+ }
+
///
public void SetSnapshotTimeIfNeeded(BsonTimestamp snapshotTime)
{
diff --git a/src/MongoDB.Driver/Core/Configuration/ClusterBuilder.cs b/src/MongoDB.Driver/Core/Configuration/ClusterBuilder.cs
index cb868f198ad..db58878eb11 100644
--- a/src/MongoDB.Driver/Core/Configuration/ClusterBuilder.cs
+++ b/src/MongoDB.Driver/Core/Configuration/ClusterBuilder.cs
@@ -36,6 +36,7 @@ public class ClusterBuilder
private ConnectionPoolSettings _connectionPoolSettings;
private ConnectionSettings _connectionSettings;
private LoggingSettings _loggingSettings;
+ private TracingOptions _tracingOptions;
private ServerSettings _serverSettings;
private SslStreamSettings _sslStreamSettings;
private Func _streamFactoryWrapper;
@@ -123,6 +124,19 @@ public ClusterBuilder ConfigureLoggingSettings(Func
+ /// Configures the tracing options.
+ ///
+ /// The tracing options configurator delegate.
+ /// A reconfigured cluster builder.
+ public ClusterBuilder ConfigureTracingOptions(Func configurator)
+ {
+ Ensure.IsNotNull(configurator, nameof(configurator));
+
+ _tracingOptions = configurator(_tracingOptions);
+ return this;
+ }
+
///
/// Configures the server settings.
///
@@ -228,6 +242,7 @@ private IConnectionPoolFactory CreateConnectionPoolFactory()
_eventAggregator,
_clusterSettings.ServerApi,
_loggingSettings.ToInternalLoggerFactory(),
+ _tracingOptions,
_tcpStreamSettings.ReadTimeout,
_tcpStreamSettings.WriteTimeout);
@@ -290,6 +305,7 @@ private IServerMonitorFactory CreateServerMonitorFactory()
new EventAggregator(),
_clusterSettings.ServerApi,
loggerFactory: null,
+ tracingOptions: new TracingOptions { Disabled = true },
_tcpStreamSettings.ReadTimeout,
_tcpStreamSettings.WriteTimeout);
diff --git a/src/MongoDB.Driver/Core/Configuration/TracingOptions.cs b/src/MongoDB.Driver/Core/Configuration/TracingOptions.cs
new file mode 100644
index 00000000000..988349db443
--- /dev/null
+++ b/src/MongoDB.Driver/Core/Configuration/TracingOptions.cs
@@ -0,0 +1,72 @@
+/* Copyright 2010-present MongoDB Inc.
+*
+* 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.
+*/
+
+using MongoDB.Shared;
+
+namespace MongoDB.Driver.Core.Configuration;
+
+///
+/// Tracing-related settings for MongoDB operations.
+///
+public sealed class TracingOptions
+{
+ ///
+ /// Gets or sets whether tracing is disabled for this client.
+ /// When set to true, no OpenTelemetry activities will be created for this client's operations.
+ /// Default is false (tracing enabled if configured via TracerProvider).
+ ///
+ public bool Disabled { get; set; }
+
+ ///
+ /// Gets or sets the maximum length of the db.query.text attribute.
+ /// Default is 0 (attribute not added).
+ ///
+ public int QueryTextMaxLength { get; set; }
+
+ internal TracingOptions Clone()
+ {
+ return new TracingOptions
+ {
+ QueryTextMaxLength = QueryTextMaxLength,
+ Disabled = Disabled
+ };
+ }
+
+ ///
+ /// Determines whether the specified TracingOptions is equal to this instance.
+ ///
+ public bool Equals(TracingOptions other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+
+ return QueryTextMaxLength == other.QueryTextMaxLength && Disabled == other.Disabled;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ return ReferenceEquals(this, obj) || obj is TracingOptions other && Equals(other);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return new Hasher()
+ .Hash(QueryTextMaxLength)
+ .Hash(Disabled)
+ .GetHashCode();
+ }
+}
\ No newline at end of file
diff --git a/src/MongoDB.Driver/Core/Connections/BinaryConnection.cs b/src/MongoDB.Driver/Core/Connections/BinaryConnection.cs
index 3359a33821e..7382257b6b4 100644
--- a/src/MongoDB.Driver/Core/Connections/BinaryConnection.cs
+++ b/src/MongoDB.Driver/Core/Connections/BinaryConnection.cs
@@ -68,6 +68,7 @@ public BinaryConnection(
IConnectionInitializer connectionInitializer,
IEventSubscriber eventSubscriber,
ILoggerFactory loggerFactory,
+ TracingOptions tracingOptions,
TimeSpan socketReadTimeout,
TimeSpan socketWriteTimeout)
{
@@ -83,7 +84,7 @@ public BinaryConnection(
_compressorSource = new CompressorSource(settings.Compressors);
_eventLogger = loggerFactory.CreateEventLogger(eventSubscriber);
- _commandEventHelper = new CommandEventHelper(loggerFactory.CreateEventLogger(eventSubscriber));
+ _commandEventHelper = new CommandEventHelper(loggerFactory.CreateEventLogger(eventSubscriber), tracingOptions);
_socketReadTimeout = socketReadTimeout;
_socketWriteTimeout = socketWriteTimeout;
}
diff --git a/src/MongoDB.Driver/Core/Connections/BinaryConnectionFactory.cs b/src/MongoDB.Driver/Core/Connections/BinaryConnectionFactory.cs
index 591814e4422..ac47956b506 100644
--- a/src/MongoDB.Driver/Core/Connections/BinaryConnectionFactory.cs
+++ b/src/MongoDB.Driver/Core/Connections/BinaryConnectionFactory.cs
@@ -32,6 +32,7 @@ internal sealed class BinaryConnectionFactory : IConnectionFactory
private readonly ILoggerFactory _loggerFactory;
private readonly ConnectionSettings _settings;
private readonly IStreamFactory _streamFactory;
+ private readonly TracingOptions _tracingOptions;
// TODO: CSOT: temporary here, remove on the next major release, together with socketTimeout
private readonly TimeSpan _socketReadTimeout;
private readonly TimeSpan _socketWriteTimeout;
@@ -43,6 +44,7 @@ public BinaryConnectionFactory(
IEventSubscriber eventSubscriber,
ServerApi serverApi,
ILoggerFactory loggerFactory,
+ TracingOptions tracingOptions,
TimeSpan? socketReadTimeout,
TimeSpan? socketWriteTimeout)
{
@@ -51,6 +53,7 @@ public BinaryConnectionFactory(
_eventSubscriber = Ensure.IsNotNull(eventSubscriber, nameof(eventSubscriber));
_connectionInitializer = new ConnectionInitializer(settings.ApplicationName, settings.Compressors, serverApi, settings.LibraryInfo);
_loggerFactory = loggerFactory;
+ _tracingOptions = tracingOptions;
_socketReadTimeout = socketReadTimeout.HasValue && socketReadTimeout > TimeSpan.Zero ? socketReadTimeout.Value : Timeout.InfiniteTimeSpan;
_socketWriteTimeout = socketWriteTimeout.HasValue && socketWriteTimeout > TimeSpan.Zero ? socketWriteTimeout.Value : Timeout.InfiniteTimeSpan;
}
@@ -70,6 +73,7 @@ public IConnection CreateConnection(ServerId serverId, EndPoint endPoint)
_connectionInitializer,
_eventSubscriber,
_loggerFactory,
+ _tracingOptions,
_socketReadTimeout,
_socketWriteTimeout);
}
diff --git a/src/MongoDB.Driver/Core/Connections/ClientDocumentHelper.cs b/src/MongoDB.Driver/Core/Connections/ClientDocumentHelper.cs
index c4be5c2cf22..482ddfda32e 100644
--- a/src/MongoDB.Driver/Core/Connections/ClientDocumentHelper.cs
+++ b/src/MongoDB.Driver/Core/Connections/ClientDocumentHelper.cs
@@ -449,7 +449,7 @@ private static bool TryGetType(string typeName, out Type type)
}
}
- private static string GetAssemblyVersion(Assembly assembly)
+ internal static string GetAssemblyVersion(Assembly assembly)
{
var versionAttribute = assembly.GetCustomAttribute();
var hashIndex = versionAttribute.InformationalVersion.IndexOf('+');
diff --git a/src/MongoDB.Driver/Core/Connections/CommandEventHelper.cs b/src/MongoDB.Driver/Core/Connections/CommandEventHelper.cs
index 1678c55c273..f731d795c04 100644
--- a/src/MongoDB.Driver/Core/Connections/CommandEventHelper.cs
+++ b/src/MongoDB.Driver/Core/Connections/CommandEventHelper.cs
@@ -21,6 +21,7 @@
using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization.Serializers;
+using MongoDB.Driver.Core.Configuration;
using MongoDB.Driver.Core.Events;
using MongoDB.Driver.Core.Logging;
using MongoDB.Driver.Core.Misc;
@@ -34,24 +35,32 @@ internal class CommandEventHelper
{
private readonly EventLogger _eventLogger;
private readonly ConcurrentDictionary _state;
+ private readonly TracingOptions _tracingOptions;
private readonly bool _shouldProcessRequestMessages;
private readonly bool _shouldTrackState;
private readonly bool _shouldTrackFailed;
private readonly bool _shouldTrackSucceeded;
+ private readonly bool _shouldTrace;
- public CommandEventHelper(EventLogger eventLogger)
+ public CommandEventHelper(EventLogger eventLogger, TracingOptions tracingOptions = null)
{
_eventLogger = eventLogger;
+ _tracingOptions = tracingOptions;
+
_shouldTrackSucceeded = _eventLogger.IsEventTracked();
_shouldTrackFailed = _eventLogger.IsEventTracked();
- _shouldTrackState = _shouldTrackSucceeded || _shouldTrackFailed;
+
+ // Check if tracing is disabled for this client
+ _shouldTrace = _tracingOptions?.Disabled != true;
+
+ _shouldTrackState = _shouldTrackSucceeded || _shouldTrackFailed || _shouldTrace;
_shouldProcessRequestMessages = _eventLogger.IsEventTracked() || _shouldTrackState;
if (_shouldTrackState)
{
// we only need to track state if we have to raise
- // a succeeded or failed event
+ // a succeeded or failed event or for tracing
_state = new ConcurrentDictionary();
}
}
@@ -104,6 +113,12 @@ public void AfterSending(RequestMessage message, ConnectionId connectionId, Obje
{
state.Stopwatch.Stop();
+ if (state.CommandActivity != null)
+ {
+ state.CommandActivity.SetStatus(ActivityStatusCode.Ok);
+ state.CommandActivity.Stop();
+ }
+
if (_shouldTrackSucceeded)
{
_eventLogger.LogAndPublish(new CommandSucceededEvent(
@@ -128,6 +143,13 @@ public void ErrorSending(RequestMessage message, ConnectionId connectionId, Obje
if (_state.TryRemove(message.RequestId, out state))
{
state.Stopwatch.Stop();
+
+ if (state.CommandActivity != null)
+ {
+ MongoTelemetry.RecordException(state.CommandActivity, exception);
+ state.CommandActivity.Stop();
+ }
+
_eventLogger.LogAndPublish(new CommandFailedEvent(
state.CommandName,
state.QueryNamespace.DatabaseNamespace,
@@ -171,6 +193,12 @@ public void ErrorReceiving(int responseTo, ConnectionId connectionId, ObjectId?
state.Stopwatch.Stop();
+ if (state.CommandActivity != null)
+ {
+ MongoTelemetry.RecordException(state.CommandActivity, exception);
+ state.CommandActivity.Stop();
+ }
+
_eventLogger.LogAndPublish(new CommandFailedEvent(
state.CommandName,
state.QueryNamespace.DatabaseNamespace,
@@ -268,7 +296,7 @@ private void ProcessCommandRequestMessage(CommandRequestMessage message, Connect
if (_shouldTrackState)
{
- _state.TryAdd(requestId, new CommandState
+ var commandState = new CommandState
{
CommandName = commandName,
OperationId = operationId,
@@ -276,7 +304,19 @@ private void ProcessCommandRequestMessage(CommandRequestMessage message, Connect
QueryNamespace = new CollectionNamespace(databaseNamespace, "$cmd"),
ExpectedResponseType = decodedMessage.MoreToCome ? ExpectedResponseType.None : ExpectedResponseType.Command,
ShouldRedactReply = shouldRedactCommand
- });
+ };
+
+ if (_shouldTrace && !shouldRedactCommand)
+ {
+ commandState.CommandActivity = MongoTelemetry.StartCommandActivity(
+ commandName,
+ command,
+ databaseNamespace,
+ connectionId,
+ _tracingOptions?.QueryTextMaxLength ?? 0);
+ }
+
+ _state.TryAdd(requestId, commandState);
}
}
}
@@ -302,6 +342,8 @@ private void ProcessCommandResponseMessage(CommandState state, CommandResponseMe
if (ok.ToBoolean())
{
+ CompleteCommandActivityWithSuccess(state.CommandActivity, reply);
+
_eventLogger.LogAndPublish(new CommandSucceededEvent(
state.CommandName,
reply,
@@ -315,23 +357,7 @@ private void ProcessCommandResponseMessage(CommandState state, CommandResponseMe
}
else
{
- if (_shouldTrackFailed)
- {
- _eventLogger.LogAndPublish(new CommandFailedEvent(
- state.CommandName,
- state.QueryNamespace.DatabaseNamespace,
- new MongoCommandException(
- connectionId,
- string.Format("{0} command failed", state.CommandName),
- null,
- reply),
- state.OperationId,
- message.ResponseTo,
- connectionId,
- serviceId,
- state.Stopwatch.Elapsed),
- skipLogging);
- }
+ HandleCommandFailure(state, reply, connectionId, serviceId, message.ResponseTo, skipLogging);
}
}
@@ -380,7 +406,7 @@ private void ProcessQueryMessage(QueryMessage originalMessage, ConnectionId conn
if (_shouldTrackState)
{
- _state.TryAdd(requestId, new CommandState
+ var commandState = new CommandState
{
CommandName = commandName,
OperationId = operationId,
@@ -388,7 +414,19 @@ private void ProcessQueryMessage(QueryMessage originalMessage, ConnectionId conn
QueryNamespace = decodedMessage.CollectionNamespace,
ExpectedResponseType = isCommand ? ExpectedResponseType.Command : ExpectedResponseType.Query,
ShouldRedactReply = shouldRedactCommand
- });
+ };
+
+ if (_shouldTrace && !shouldRedactCommand)
+ {
+ commandState.CommandActivity = MongoTelemetry.StartCommandActivity(
+ commandName,
+ command,
+ decodedMessage.CollectionNamespace.DatabaseNamespace,
+ connectionId,
+ _tracingOptions?.QueryTextMaxLength ?? 0);
+ }
+
+ _state.TryAdd(requestId, commandState);
}
}
finally
@@ -493,25 +531,12 @@ private void ProcessCommandReplyMessage(CommandState state, ReplyMessage(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "bulkWrite");
}
///
@@ -161,7 +161,7 @@ public Task BulkWriteAsync(IClientSessionHandle session,
Ensure.IsNotNull(session, nameof(session));
ThrowIfDisposed();
var operation = CreateClientBulkWriteOperation(models, options);
- return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "bulkWrite");
}
///
@@ -341,7 +341,7 @@ public IAsyncCursor ListDatabases(
ThrowIfDisposed();
Ensure.IsNotNull(session, nameof(session));
var operation = CreateListDatabasesOperation(options);
- return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken, "listDatabases");
}
///
@@ -377,7 +377,7 @@ public Task> ListDatabasesAsync(
Ensure.IsNotNull(session, nameof(session));
ThrowIfDisposed();
var operation = CreateListDatabasesOperation(options);
- return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken, "listDatabases");
}
///
@@ -563,7 +563,7 @@ private ChangeStreamOperation CreateChangeStreamOperation(
_settings.RetryReads,
_settings.TranslationOptions);
- private OperationContext CreateOperationContext(IClientSessionHandle session, TimeSpan? timeout, CancellationToken cancellationToken)
+ private OperationContext CreateOperationContext(IClientSessionHandle session, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
var operationContext = session.WrappedCoreSession.CurrentTransaction?.OperationContext;
if (operationContext != null && timeout != null)
@@ -571,32 +571,43 @@ private OperationContext CreateOperationContext(IClientSessionHandle session, Ti
throw new InvalidOperationException("Cannot specify per operation timeout inside transaction.");
}
- return operationContext?.Fork() ?? new OperationContext(timeout ?? _settings.Timeout, cancellationToken);
+ var context = operationContext?.Fork() ?? new OperationContext(timeout ?? _settings.Timeout, cancellationToken);
+
+ // Set operation metadata for OpenTelemetry tracing
+ // Client-level operations (like bulkWrite) use "admin" as database name
+ if (operationName != null)
+ {
+ var tracingOptions = _settings.TracingOptions;
+ var isTracingEnabled = tracingOptions == null || !tracingOptions.Disabled;
+ context = context.WithOperationMetadata(operationName, "admin", null, isTracingEnabled);
+ }
+
+ return context;
}
- private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
+ private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
var readPreference = session.GetEffectiveReadPreference(_settings.ReadPreference);
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return _operationExecutor.ExecuteReadOperation(operationContext, session, operation, readPreference, false);
}
- private async Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
+ private async Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
var readPreference = session.GetEffectiveReadPreference(_settings.ReadPreference);
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return await _operationExecutor.ExecuteReadOperationAsync(operationContext, session, operation, readPreference, false).ConfigureAwait(false);
}
- private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
+ private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return _operationExecutor.ExecuteWriteOperation(operationContext, session, operation, false);
}
- private async Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
+ private async Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return await _operationExecutor.ExecuteWriteOperationAsync(operationContext, session, operation, false).ConfigureAwait(false);
}
diff --git a/src/MongoDB.Driver/MongoClientSettings.cs b/src/MongoDB.Driver/MongoClientSettings.cs
index 652e1ccf87e..41f54a5ddbf 100644
--- a/src/MongoDB.Driver/MongoClientSettings.cs
+++ b/src/MongoDB.Driver/MongoClientSettings.cs
@@ -76,6 +76,7 @@ public class MongoClientSettings : IEquatable, IInheritable
private string _srvServiceName;
private SslSettings _sslSettings;
private TimeSpan? _timeout;
+ private TracingOptions _tracingOptions;
private ExpressionTranslationOptions _translationOptions;
private bool _useTls;
private int _waitQueueSize;
@@ -367,6 +368,19 @@ public LoggingSettings LoggingSettings
}
}
+ ///
+ /// Gets or sets the tracing options for OpenTelemetry instrumentation.
+ ///
+ public TracingOptions TracingOptions
+ {
+ get { return _tracingOptions; }
+ set
+ {
+ if (_isFrozen) { throw new InvalidOperationException("MongoClientSettings is frozen."); }
+ _tracingOptions = value;
+ }
+ }
+
///
/// Gets or sets the maximum concurrently connecting connections.
///
@@ -952,6 +966,7 @@ public MongoClientSettings Clone()
clone._loadBalanced = _loadBalanced;
clone._localThreshold = _localThreshold;
clone._loggingSettings = _loggingSettings;
+ clone._tracingOptions = _tracingOptions?.Clone();
clone._maxConnecting = _maxConnecting;
clone._maxConnectionIdleTime = _maxConnectionIdleTime;
clone._maxConnectionLifeTime = _maxConnectionLifeTime;
@@ -1023,6 +1038,7 @@ public override bool Equals(object obj)
_loadBalanced == rhs._loadBalanced &&
_localThreshold == rhs._localThreshold &&
_loggingSettings == rhs._loggingSettings &&
+ object.Equals(_tracingOptions, rhs._tracingOptions) &&
_maxConnecting == rhs._maxConnecting &&
_maxConnectionIdleTime == rhs._maxConnectionIdleTime &&
_maxConnectionLifeTime == rhs._maxConnectionLifeTime &&
@@ -1258,6 +1274,7 @@ internal ClusterKey ToClusterKey()
_loadBalanced,
_localThreshold,
_loggingSettings,
+ _tracingOptions,
_maxConnecting,
_maxConnectionIdleTime,
_maxConnectionLifeTime,
diff --git a/src/MongoDB.Driver/MongoCollectionImpl.cs b/src/MongoDB.Driver/MongoCollectionImpl.cs
index a083a40c453..e60e5701189 100644
--- a/src/MongoDB.Driver/MongoCollectionImpl.cs
+++ b/src/MongoDB.Driver/MongoCollectionImpl.cs
@@ -109,13 +109,13 @@ public override IAsyncCursor Aggregate(IClientSessionHandle se
if (isAggregateToCollection)
{
var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options);
- ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken);
+ ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate");
return CreateAggregateToCollectionResultCursor(session, renderedPipeline, options);
}
else
{
var aggregateOperation = CreateAggregateOperation(renderedPipeline, options);
- return ExecuteReadOperation(session, aggregateOperation, options.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate");
}
}
@@ -136,13 +136,13 @@ public override async Task> AggregateAsync(IClien
if (isAggregateToCollection)
{
var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options);
- await ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken).ConfigureAwait(false);
+ await ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate").ConfigureAwait(false);
return CreateAggregateToCollectionResultCursor(session, renderedPipeline, options);
}
else
{
var aggregateOperation = CreateAggregateOperation(renderedPipeline, options);
- return await ExecuteReadOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken).ConfigureAwait(false);
+ return await ExecuteReadOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate").ConfigureAwait(false);
}
}
@@ -166,7 +166,7 @@ public override void AggregateToCollection(IClientSessionHandle session
}
var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options);
- ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken);
+ ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate");
}
public override async Task AggregateToCollectionAsync(PipelineDefinition pipeline, AggregateOptions options, CancellationToken cancellationToken = default)
@@ -208,10 +208,13 @@ public override BulkWriteResult BulkWrite(IClientSessionHandle sessio
throw new ArgumentException("Must contain at least 1 request.", nameof(requests));
}
+ // Infer operation name from write model types
+ var operationName = GetOperationNameFromWriteModels(requestsArray);
+
var operation = CreateBulkWriteOperation(session, requestsArray, options);
try
{
- var result = ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ var result = ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, operationName);
return BulkWriteResult.FromCore(result, requestsArray);
}
catch (MongoBulkWriteOperationException ex)
@@ -236,10 +239,13 @@ public override async Task> BulkWriteAsync(IClientSes
throw new ArgumentException("Must contain at least 1 request.", nameof(requests));
}
+ // Infer operation name from write model types
+ var operationName = GetOperationNameFromWriteModels(requestsArray);
+
var operation = CreateBulkWriteOperation(session, requestsArray, options);
try
{
- var result = await ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken).ConfigureAwait(false);
+ var result = await ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, operationName).ConfigureAwait(false);
return BulkWriteResult.FromCore(result, requestsArray);
}
catch (MongoBulkWriteOperationException ex)
@@ -262,7 +268,7 @@ public override long Count(IClientSessionHandle session, FilterDefinition CountAsync(IClientSessionHandle session, FilterDefini
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateCountOperation(filter, options);
- return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken, "count");
}
public override long CountDocuments(FilterDefinition filter, CountOptions options, CancellationToken cancellationToken = default)
@@ -294,7 +300,7 @@ public override long CountDocuments(IClientSessionHandle session, FilterDefiniti
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateCountDocumentsOperation(filter, options);
- return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken, "countDocuments");
}
public override async Task CountDocumentsAsync(FilterDefinition filter, CountOptions options, CancellationToken cancellationToken = default)
@@ -309,7 +315,7 @@ public override Task CountDocumentsAsync(IClientSessionHandle session, Fil
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateCountDocumentsOperation(filter, options);
- return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken, "countDocuments");
}
public override IAsyncCursor Distinct(FieldDefinition field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default)
@@ -325,7 +331,7 @@ public override IAsyncCursor Distinct(IClientSessionHandle sessi
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateDistinctOperation(field, filter, options);
- return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken, "distinct");
}
public override async Task> DistinctAsync(FieldDefinition field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default)
@@ -341,7 +347,7 @@ public override Task> DistinctAsync(IClientSessionH
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateDistinctOperation(field, filter, options);
- return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken, "distinct");
}
public override IAsyncCursor DistinctMany(FieldDefinition> field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default)
@@ -357,7 +363,7 @@ public override IAsyncCursor DistinctMany(IClientSessionHandle ses
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateDistinctManyOperation(field, filter, options);
- return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken, "distinct");
}
public override async Task> DistinctManyAsync(FieldDefinition> field, FilterDefinition filter, DistinctOptions options, CancellationToken cancellationToken = default)
@@ -373,21 +379,21 @@ public override Task> DistinctManyAsync(IClientSessio
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateDistinctManyOperation(field, filter, options);
- return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken, "distinct");
}
public override long EstimatedDocumentCount(EstimatedDocumentCountOptions options, CancellationToken cancellationToken = default)
{
using var session = _operationExecutor.StartImplicitSession();
var operation = CreateEstimatedDocumentCountOperation(options);
- return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken, "count");
}
public override async Task EstimatedDocumentCountAsync(EstimatedDocumentCountOptions options, CancellationToken cancellationToken = default)
{
using var session = _operationExecutor.StartImplicitSession();
var operation = CreateEstimatedDocumentCountOperation(options);
- return await ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken).ConfigureAwait(false);
+ return await ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken, "count").ConfigureAwait(false);
}
public override IAsyncCursor FindSync(FilterDefinition filter, FindOptions options, CancellationToken cancellationToken = default)
@@ -402,7 +408,7 @@ public override IAsyncCursor FindSync(IClientSessionHa
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateFindOperation(filter, options);
- return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken, "find");
}
public override async Task> FindAsync(FilterDefinition filter, FindOptions options, CancellationToken cancellationToken = default)
@@ -417,7 +423,7 @@ public override Task> FindAsync(IClientSe
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateFindOperation(filter, options);
- return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken, "find");
}
public override TProjection FindOneAndDelete(FilterDefinition filter, FindOneAndDeleteOptions options, CancellationToken cancellationToken = default)
@@ -432,7 +438,7 @@ public override TProjection FindOneAndDelete(IClientSessionHandle s
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateFindOneAndDeleteOperation(filter, options);
- return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "findAndModify");
}
public override async Task FindOneAndDeleteAsync(FilterDefinition filter, FindOneAndDeleteOptions options, CancellationToken cancellationToken = default)
@@ -447,7 +453,7 @@ public override Task FindOneAndDeleteAsync(IClientSess
Ensure.IsNotNull(filter, nameof(filter));
var operation = CreateFindOneAndDeleteOperation(filter, options);
- return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "findAndModify");
}
public override TProjection FindOneAndReplace(FilterDefinition filter, TDocument replacement, FindOneAndReplaceOptions options, CancellationToken cancellationToken = default)
@@ -463,7 +469,7 @@ public override TProjection FindOneAndReplace(IClientSessionHandle
var replacementObject = Ensure.IsNotNull((object)replacement, nameof(replacement)); // only box once if it's a struct
var operation = CreateFindOneAndReplaceOperation(filter, replacementObject, options);
- return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "findAndModify");
}
public override async Task FindOneAndReplaceAsync(FilterDefinition filter, TDocument replacement, FindOneAndReplaceOptions options, CancellationToken cancellationToken = default)
@@ -479,7 +485,7 @@ public override Task FindOneAndReplaceAsync(IClientSes
var replacementObject = Ensure.IsNotNull((object)replacement, nameof(replacement)); // only box once if it's a struct
var operation = CreateFindOneAndReplaceOperation(filter, replacementObject, options);
- return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "findAndModify");
}
public override TProjection FindOneAndUpdate(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options, CancellationToken cancellationToken = default)
@@ -501,7 +507,7 @@ public override TProjection FindOneAndUpdate(IClientSessionHandle s
}
var operation = CreateFindOneAndUpdateOperation(filter, update, options);
- return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "findAndModify");
}
public override async Task FindOneAndUpdateAsync(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options, CancellationToken cancellationToken = default)
@@ -522,7 +528,7 @@ public override Task FindOneAndUpdateAsync(IClientSess
}
var operation = CreateFindOneAndUpdateOperation(filter, update, options);
- return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "findAndModify");
}
[Obsolete("Use Aggregation pipeline instead.")]
@@ -547,12 +553,12 @@ public override IAsyncCursor MapReduce(IClientSessionHandle se
if (outputOptions == MapReduceOutputOptions.Inline)
{
var operation = CreateMapReduceOperation(map, reduce, options, resultSerializer, renderArgs);
- return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, operation, options.Timeout, cancellationToken, "mapReduce");
}
else
{
var mapReduceOperation = CreateMapReduceOutputToCollectionOperation(map, reduce, options, outputOptions, renderArgs);
- ExecuteWriteOperation(session, mapReduceOperation, options.Timeout, cancellationToken);
+ ExecuteWriteOperation(session, mapReduceOperation, options.Timeout, cancellationToken, "mapReduce");
return CreateMapReduceOutputToCollectionResultCursor(session, options, mapReduceOperation.OutputCollectionNamespace, resultSerializer);
}
}
@@ -579,12 +585,12 @@ public override async Task> MapReduceAsync(IClien
if (outputOptions == MapReduceOutputOptions.Inline)
{
var operation = CreateMapReduceOperation(map, reduce, options, resultSerializer, renderArgs);
- return await ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken).ConfigureAwait(false);
+ return await ExecuteReadOperationAsync(session, operation, options.Timeout, cancellationToken, "mapReduce").ConfigureAwait(false);
}
else
{
var mapReduceOperation = CreateMapReduceOutputToCollectionOperation(map, reduce, options, outputOptions, renderArgs);
- await ExecuteWriteOperationAsync(session, mapReduceOperation, options.Timeout, cancellationToken).ConfigureAwait(false);
+ await ExecuteWriteOperationAsync(session, mapReduceOperation, options.Timeout, cancellationToken, "mapReduce").ConfigureAwait(false);
return CreateMapReduceOutputToCollectionResultCursor(session, options, mapReduceOperation.OutputCollectionNamespace, resultSerializer);
}
}
@@ -1199,7 +1205,7 @@ private IAsyncCursor CreateMapReduceOutputToCollectionResultCursor(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
- => ExecuteReadOperation(session, operation, null, timeout, cancellationToken);
+ private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
+ => ExecuteReadOperation(session, operation, null, timeout, cancellationToken, operationName);
- private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken)
+ private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
var readPreference = explicitReadPreference ?? session.GetEffectiveReadPreference(_settings.ReadPreference);
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return _operationExecutor.ExecuteReadOperation(operationContext, session, operation, readPreference, true);
}
- private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
- => ExecuteReadOperationAsync(session, operation, null, timeout, cancellationToken);
+ private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
+ => ExecuteReadOperationAsync(session, operation, null, timeout, cancellationToken, operationName);
- private async Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken)
+ private async Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
var readPreference = explicitReadPreference ?? session.GetEffectiveReadPreference(_settings.ReadPreference);
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return await _operationExecutor.ExecuteReadOperationAsync(operationContext, session, operation, readPreference, true).ConfigureAwait(false);
}
- private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
+ private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return _operationExecutor.ExecuteWriteOperation(operationContext, session, operation, true);
}
- private async Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
+ private async Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return await _operationExecutor.ExecuteWriteOperationAsync(operationContext, session, operation, true).ConfigureAwait(false);
}
+ private string GetOperationNameFromWriteModels(WriteModel[] requests)
+ {
+ // Check if all requests are of the same type
+ var firstType = requests[0].ModelType;
+ var allSameType = requests.All(r => r.ModelType == firstType);
+
+ if (allSameType)
+ {
+ return firstType switch
+ {
+ WriteModelType.InsertOne => "insert",
+ WriteModelType.DeleteOne => "delete",
+ WriteModelType.DeleteMany => "delete",
+ WriteModelType.UpdateOne => "update",
+ WriteModelType.UpdateMany => "update",
+ WriteModelType.ReplaceOne => "update",
+ _ => "bulkWrite"
+ };
+ }
+
+ // Mixed operation types
+ return "bulkWrite";
+ }
+
private MessageEncoderSettings GetMessageEncoderSettings()
{
var messageEncoderSettings = new MessageEncoderSettings
@@ -1402,7 +1446,7 @@ public override IEnumerable CreateMany(
Ensure.IsNotNull(models, nameof(models));
var operation = CreateCreateIndexesOperation(models, options);
- _collection.ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ _collection.ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "createIndexes");
return operation.Requests.Select(x => x.GetIndexName());
}
@@ -1431,7 +1475,7 @@ public override async Task> CreateManyAsync(
Ensure.IsNotNull(models, nameof(models));
var operation = CreateCreateIndexesOperation(models, options);
- await _collection.ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken).ConfigureAwait(false);
+ await _collection.ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "createIndexes").ConfigureAwait(false);
return operation.Requests.Select(x => x.GetIndexName());
}
@@ -1451,7 +1495,7 @@ public override void DropAll(IClientSessionHandle session, DropIndexOptions opti
{
Ensure.IsNotNull(session, nameof(session));
var operation = CreateDropAllOperation(options);
- _collection.ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ _collection.ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "dropIndexes");
}
public override Task DropAllAsync(CancellationToken cancellationToken)
@@ -1470,7 +1514,7 @@ public override Task DropAllAsync(IClientSessionHandle session, DropIndexOptions
{
Ensure.IsNotNull(session, nameof(session));
var operation = CreateDropAllOperation(options);
- return _collection.ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return _collection.ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "dropIndexes");
}
public override void DropOne(string name, CancellationToken cancellationToken = default)
@@ -1495,7 +1539,7 @@ public override void DropOne(IClientSessionHandle session, string name, DropInde
}
var operation = CreateDropOneOperation(name, options);
- _collection.ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ _collection.ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "dropIndexes");
}
public override Task DropOneAsync(string name, CancellationToken cancellationToken = default)
@@ -1520,7 +1564,7 @@ public override Task DropOneAsync(IClientSessionHandle session, string name, Dro
}
var operation = CreateDropOneOperation(name, options);
- return _collection.ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return _collection.ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "dropIndexes");
}
public override IAsyncCursor List(CancellationToken cancellationToken = default)
@@ -1539,7 +1583,7 @@ public override IAsyncCursor List(IClientSessionHandle session, Li
{
Ensure.IsNotNull(session, nameof(session));
var operation = CreateListIndexesOperation(options);
- return _collection.ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken);
+ return _collection.ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken, "listIndexes");
}
public override Task> ListAsync(CancellationToken cancellationToken = default)
@@ -1558,7 +1602,7 @@ public override Task> ListAsync(IClientSessionHandle
{
Ensure.IsNotNull(session, nameof(session));
var operation = CreateListIndexesOperation(options);
- return _collection.ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return _collection.ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken, "listIndexes");
}
// private methods
@@ -1660,7 +1704,7 @@ public IEnumerable CreateMany(IEnumerable models
using var session = _collection._operationExecutor.StartImplicitSession();
var operation = CreateCreateIndexesOperation(models);
// TODO: CSOT: find a way to add timeout parameter to the interface method
- var result = _collection.ExecuteWriteOperation(session, operation, null, cancellationToken);
+ var result = _collection.ExecuteWriteOperation(session, operation, null, cancellationToken, "createSearchIndexes");
return GetIndexNames(result);
}
@@ -1669,7 +1713,7 @@ public async Task> CreateManyAsync(IEnumerable List(string indexName, AggregateOptions aggregateOptions = null, CancellationToken cancellationToken = default)
@@ -1722,7 +1766,7 @@ public void Update(string indexName, BsonDocument definition, CancellationToken
using var session = _collection._operationExecutor.StartImplicitSession();
var operation = new UpdateSearchIndexOperation(_collection.CollectionNamespace, indexName, definition, _collection._messageEncoderSettings);
// TODO: CSOT: find a way to add timeout parameter to the interface method
- _collection.ExecuteWriteOperation(session, operation, null, cancellationToken);
+ _collection.ExecuteWriteOperation(session, operation, null, cancellationToken, "updateSearchIndex");
}
public async Task UpdateAsync(string indexName, BsonDocument definition, CancellationToken cancellationToken = default)
@@ -1730,7 +1774,7 @@ public async Task UpdateAsync(string indexName, BsonDocument definition, Cancell
using var session = _collection._operationExecutor.StartImplicitSession();
var operation = new UpdateSearchIndexOperation(_collection.CollectionNamespace, indexName, definition, _collection._messageEncoderSettings);
// TODO: CSOT: find a way to add timeout parameter to the interface method
- await _collection.ExecuteWriteOperationAsync(session, operation, null, cancellationToken).ConfigureAwait(false);
+ await _collection.ExecuteWriteOperationAsync(session, operation, null, cancellationToken, "updateSearchIndex").ConfigureAwait(false);
}
// private methods
diff --git a/src/MongoDB.Driver/MongoDB.Driver.csproj b/src/MongoDB.Driver/MongoDB.Driver.csproj
index 34add76dfbe..2bafad80017 100644
--- a/src/MongoDB.Driver/MongoDB.Driver.csproj
+++ b/src/MongoDB.Driver/MongoDB.Driver.csproj
@@ -26,6 +26,7 @@
+
diff --git a/src/MongoDB.Driver/MongoDatabase.cs b/src/MongoDB.Driver/MongoDatabase.cs
index 31b872da989..8ccc9aac2b6 100644
--- a/src/MongoDB.Driver/MongoDatabase.cs
+++ b/src/MongoDB.Driver/MongoDatabase.cs
@@ -73,13 +73,13 @@ public IAsyncCursor Aggregate(IClientSessionHandle session, Pi
if (isAggregateToCollection)
{
var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options);
- ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken);
+ ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate");
return CreateAggregateToCollectionResultCursor(session, renderedPipeline, options);
}
else
{
var aggregateOperation = CreateAggregateOperation(renderedPipeline, options);
- return ExecuteReadOperation(session, aggregateOperation, options.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate");
}
}
@@ -100,13 +100,13 @@ public async Task> AggregateAsync(IClientSessionH
if (isAggregateToCollection)
{
var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options);
- await ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken).ConfigureAwait(false);
+ await ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate").ConfigureAwait(false);
return CreateAggregateToCollectionResultCursor(session, renderedPipeline, options);
}
else
{
var aggregateOperation = CreateAggregateOperation(renderedPipeline, options);
- return await ExecuteReadOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken).ConfigureAwait(false);
+ return await ExecuteReadOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate").ConfigureAwait(false);
}
}
@@ -130,7 +130,7 @@ public void AggregateToCollection(IClientSessionHandle session, Pipelin
}
var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options);
- ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken);
+ ExecuteWriteOperation(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate");
}
public async Task AggregateToCollectionAsync(PipelineDefinition pipeline, AggregateOptions options, CancellationToken cancellationToken = default)
@@ -153,7 +153,7 @@ public Task AggregateToCollectionAsync(IClientSessionHandle session, Pi
}
var aggregateOperation = CreateAggregateToCollectionOperation(renderedPipeline, options);
- return ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken);
+ return ExecuteWriteOperationAsync(session, aggregateOperation, options.Timeout, cancellationToken, "aggregate");
}
public void CreateCollection(string name, CreateCollectionOptions options, CancellationToken cancellationToken)
@@ -244,7 +244,7 @@ public void CreateView(IClientSessionHandle session, string
Ensure.IsNotNull(pipeline, nameof(pipeline));
var operation = CreateCreateViewOperation(viewName, viewOn, pipeline, options);
- ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "create", viewName);
}
public async Task CreateViewAsync(string viewName, string viewOn, PipelineDefinition pipeline, CreateViewOptions options = null, CancellationToken cancellationToken = default)
@@ -261,7 +261,7 @@ public Task CreateViewAsync(IClientSessionHandle session, st
Ensure.IsNotNull(pipeline, nameof(pipeline));
var operation = CreateCreateViewOperation(viewName, viewOn, pipeline, options);
- return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "create", viewName);
}
public void DropCollection(string name, CancellationToken cancellationToken)
@@ -288,7 +288,7 @@ public void DropCollection(IClientSessionHandle session, string name, DropCollec
var collectionNamespace = new CollectionNamespace(_databaseNamespace, name);
var encryptedFields = GetEffectiveEncryptedFields(session, collectionNamespace, options, cancellationToken);
var operation = CreateDropCollectionOperation(collectionNamespace, encryptedFields);
- ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "dropCollection", name);
}
public Task DropCollectionAsync(string name, CancellationToken cancellationToken)
@@ -311,7 +311,7 @@ public async Task DropCollectionAsync(IClientSessionHandle session, string name,
var collectionNamespace = new CollectionNamespace(_databaseNamespace, name);
var encryptedFields = await GetEffectiveEncryptedFieldsAsync(session, collectionNamespace, options, cancellationToken).ConfigureAwait(false);
var operation = CreateDropCollectionOperation(collectionNamespace, encryptedFields);
- await ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken).ConfigureAwait(false);
+ await ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "dropCollection", name).ConfigureAwait(false);
}
public IMongoCollection GetCollection(string name, MongoCollectionSettings settings)
@@ -338,7 +338,7 @@ public IAsyncCursor ListCollectionNames(IClientSessionHandle session, Li
Ensure.IsNotNull(session, nameof(session));
var operation = CreateListCollectionNamesOperation(options);
var readPreference = session.GetEffectiveReadPreference(ReadPreference.Primary);
- var cursor = ExecuteReadOperation(session, operation, readPreference, options?.Timeout, cancellationToken);
+ var cursor = ExecuteReadOperation(session, operation, readPreference, options?.Timeout, cancellationToken, "listCollections");
return new BatchTransformingAsyncCursor(cursor, ExtractCollectionNames);
}
@@ -353,7 +353,7 @@ public async Task> ListCollectionNamesAsync(IClientSessionH
Ensure.IsNotNull(session, nameof(session));
var operation = CreateListCollectionNamesOperation(options);
var readPreference = session.GetEffectiveReadPreference(ReadPreference.Primary);
- var cursor = await ExecuteReadOperationAsync(session, operation, readPreference, options?.Timeout, cancellationToken).ConfigureAwait(false);
+ var cursor = await ExecuteReadOperationAsync(session, operation, readPreference, options?.Timeout, cancellationToken, "listCollections").ConfigureAwait(false);
return new BatchTransformingAsyncCursor(cursor, ExtractCollectionNames);
}
@@ -368,7 +368,7 @@ public IAsyncCursor ListCollections(IClientSessionHandle session,
Ensure.IsNotNull(session, nameof(session));
var operation = CreateListCollectionsOperation(options);
var readPreference = session.GetEffectiveReadPreference(ReadPreference.Primary);
- return ExecuteReadOperation(session, operation, readPreference, options?.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, operation, readPreference, options?.Timeout, cancellationToken, "listCollections");
}
public async Task> ListCollectionsAsync(ListCollectionsOptions options, CancellationToken cancellationToken)
@@ -382,7 +382,7 @@ public Task> ListCollectionsAsync(IClientSessionHandl
Ensure.IsNotNull(session, nameof(session));
var operation = CreateListCollectionsOperation(options);
var readPreference = session.GetEffectiveReadPreference(ReadPreference.Primary);
- return ExecuteReadOperationAsync(session, operation, readPreference, options?.Timeout, cancellationToken);
+ return ExecuteReadOperationAsync(session, operation, readPreference, options?.Timeout, cancellationToken, "listCollections");
}
public void RenameCollection(string oldName, string newName, RenameCollectionOptions options, CancellationToken cancellationToken)
@@ -398,7 +398,7 @@ public void RenameCollection(IClientSessionHandle session, string oldName, strin
Ensure.IsNotNullOrEmpty(newName, nameof(newName));
var operation = CreateRenameCollectionOperation(oldName, newName, options);
- ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "renameCollection");
}
public async Task RenameCollectionAsync(string oldName, string newName, RenameCollectionOptions options, CancellationToken cancellationToken)
@@ -414,7 +414,7 @@ public Task RenameCollectionAsync(IClientSessionHandle session, string oldName,
Ensure.IsNotNullOrEmpty(newName, nameof(newName));
var operation = CreateRenameCollectionOperation(oldName, newName, options);
- return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "renameCollection");
}
public TResult RunCommand(Command command, ReadPreference readPreference = null, CancellationToken cancellationToken = default)
@@ -480,7 +480,7 @@ public IChangeStreamCursor Watch(
Ensure.IsNotNull(pipeline, nameof(pipeline));
var operation = CreateChangeStreamOperation(pipeline, options);
- return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperation(session, operation, options?.Timeout, cancellationToken, "aggregate");
}
public async Task> WatchAsync(
@@ -502,7 +502,7 @@ public Task> WatchAsync(
Ensure.IsNotNull(pipeline, nameof(pipeline));
var operation = CreateChangeStreamOperation(pipeline, options);
- return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteReadOperationAsync(session, operation, options?.Timeout, cancellationToken, "aggregate");
}
public IMongoDatabase WithReadConcern(ReadConcern readConcern)
@@ -608,13 +608,13 @@ private AggregateToCollectionOperation CreateAggregateToCollectionOperation(IClientSessionHandle session, string name, CreateCollectionOptions options, CancellationToken cancellationToken)
{
var operation = CreateCreateCollectionOperation(name, options);
- ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken);
+ ExecuteWriteOperation(session, operation, options?.Timeout, cancellationToken, "createCollection", name);
}
private Task CreateCollectionHelperAsync(IClientSessionHandle session, string name, CreateCollectionOptions options, CancellationToken cancellationToken)
{
var operation = CreateCreateCollectionOperation(name, options);
- return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken);
+ return ExecuteWriteOperationAsync(session, operation, options?.Timeout, cancellationToken, "createCollection", name);
}
private IWriteOperation CreateCreateCollectionOperation(string name, CreateCollectionOptions options)
@@ -755,7 +755,7 @@ private ChangeStreamOperation CreateChangeStreamOperation(
translationOptions);
}
- private OperationContext CreateOperationContext(IClientSessionHandle session, TimeSpan? timeout, CancellationToken cancellationToken)
+ private OperationContext CreateOperationContext(IClientSessionHandle session, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null, string collectionName = null)
{
var operationContext = session.WrappedCoreSession.CurrentTransaction?.OperationContext;
if (operationContext != null && timeout != null)
@@ -763,38 +763,48 @@ private OperationContext CreateOperationContext(IClientSessionHandle session, Ti
throw new InvalidOperationException("Cannot specify per operation timeout inside transaction.");
}
- return operationContext?.Fork() ?? new OperationContext(timeout ?? _settings.Timeout, cancellationToken);
+ var context = operationContext?.Fork() ?? new OperationContext(timeout ?? _settings.Timeout, cancellationToken);
+
+ // Set operation metadata for OpenTelemetry tracing
+ if (operationName != null)
+ {
+ var tracingOptions = _client.Settings.TracingOptions;
+ var isTracingEnabled = tracingOptions == null || !tracingOptions.Disabled;
+ context = context.WithOperationMetadata(operationName, _databaseNamespace.DatabaseName, collectionName, isTracingEnabled);
+ }
+
+ return context;
}
- private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
- => ExecuteReadOperation(session, operation, null, timeout, cancellationToken);
+ private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
+ => ExecuteReadOperation(session, operation, null, timeout, cancellationToken, operationName);
- private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken)
+ private TResult ExecuteReadOperation(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
var readPreference = explicitReadPreference ?? session.GetEffectiveReadPreference(_settings.ReadPreference);
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return _operationExecutor.ExecuteReadOperation(operationContext, session, operation, readPreference, true);
}
- private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
- => ExecuteReadOperationAsync(session, operation, null, timeout, cancellationToken);
+ private Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
+ => ExecuteReadOperationAsync(session, operation, null, timeout, cancellationToken, operationName);
- private async Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken)
+ private async Task ExecuteReadOperationAsync(IClientSessionHandle session, IReadOperation operation, ReadPreference explicitReadPreference, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null)
{
var readPreference = explicitReadPreference ?? session.GetEffectiveReadPreference(_settings.ReadPreference);
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName);
return await _operationExecutor.ExecuteReadOperationAsync(operationContext, session, operation, readPreference, true).ConfigureAwait(false);
}
- private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
+ private TResult ExecuteWriteOperation(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null, string collectionName = null)
{
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName, collectionName);
return _operationExecutor.ExecuteWriteOperation(operationContext, session, operation, true);
}
- private async Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken)
+ private async Task ExecuteWriteOperationAsync(IClientSessionHandle session, IWriteOperation operation, TimeSpan? timeout, CancellationToken cancellationToken, string operationName = null, string collectionName = null)
{
- using var operationContext = CreateOperationContext(session, timeout, cancellationToken);
+ using var operationContext = CreateOperationContext(session, timeout, cancellationToken, operationName, collectionName);
return await _operationExecutor.ExecuteWriteOperationAsync(operationContext, session, operation, true).ConfigureAwait(false);
}
diff --git a/src/MongoDB.Driver/MongoTelemetry.cs b/src/MongoDB.Driver/MongoTelemetry.cs
new file mode 100644
index 00000000000..ed35c815ab9
--- /dev/null
+++ b/src/MongoDB.Driver/MongoTelemetry.cs
@@ -0,0 +1,239 @@
+/* Copyright 2010-present MongoDB Inc.
+*
+* 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.
+*/
+
+using System;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Sockets;
+using MongoDB.Bson;
+using MongoDB.Driver.Core.Connections;
+
+namespace MongoDB.Driver;
+
+///
+/// Provides access to MongoDB driver's OpenTelemetry instrumentation.
+///
+public static class MongoTelemetry
+{
+ private static readonly string s_driverVersion = ClientDocumentHelper.GetAssemblyVersion(typeof(MongoClient).Assembly);
+
+ ///
+ /// The ActivitySource used by MongoDB driver for OpenTelemetry tracing.
+ /// Applications can subscribe to this source to receive MongoDB traces.
+ ///
+ public static readonly ActivitySource ActivitySource = new("MongoDB.Driver", s_driverVersion);
+
+ internal static Activity StartOperationActivity(string operationName, string databaseName, string collectionName = null)
+ {
+ if (string.IsNullOrEmpty(operationName))
+ {
+ return null;
+ }
+
+ var spanName = GetSpanName(operationName, databaseName, collectionName);
+ var activity = ActivitySource.StartActivity(spanName, ActivityKind.Client);
+
+ if (activity?.IsAllDataRequested == true)
+ {
+ activity.SetTag("db.system", "mongodb");
+ activity.SetTag("db.operation.name", operationName);
+ activity.SetTag("db.operation.summary", spanName);
+
+ if (!string.IsNullOrEmpty(databaseName))
+ {
+ activity.SetTag("db.namespace", databaseName);
+ }
+
+ if (!string.IsNullOrEmpty(collectionName))
+ {
+ activity.SetTag("db.collection.name", collectionName);
+ }
+ }
+
+ return activity;
+ }
+
+ internal static Activity StartTransactionActivity()
+ {
+ var activity = ActivitySource.StartActivity("transaction", ActivityKind.Client);
+
+ if (activity?.IsAllDataRequested == true)
+ {
+ activity.SetTag("db.system", "mongodb");
+ }
+
+ return activity;
+ }
+
+ internal static string GetSpanName(string name, string databaseName, string collectionName)
+ {
+ if (!string.IsNullOrEmpty(collectionName))
+ {
+ return $"{name} {databaseName}.{collectionName}";
+ }
+ if (!string.IsNullOrEmpty(databaseName))
+ {
+ return $"{name} {databaseName}";
+ }
+ return name;
+ }
+
+ internal static Activity StartCommandActivity(
+ string commandName,
+ BsonDocument command,
+ DatabaseNamespace databaseNamespace,
+ ConnectionId connectionId,
+ int queryTextMaxLength = 0)
+ {
+ var activity = ActivitySource.StartActivity(commandName, ActivityKind.Client);
+
+ if (activity == null)
+ {
+ return null;
+ }
+
+ if (activity.IsAllDataRequested)
+ {
+ var collectionName = ExtractCollectionName(command);
+ activity.SetTag("db.system", "mongodb");
+ activity.SetTag("db.command.name", commandName);
+ activity.SetTag("db.namespace", databaseNamespace.DatabaseName);
+
+ if (!string.IsNullOrEmpty(collectionName))
+ {
+ activity.SetTag("db.collection.name", collectionName);
+ }
+
+ // db.query.summary uses the full format like operation-level spans
+ var querySummary = GetSpanName(commandName, databaseNamespace.DatabaseName, collectionName);
+ activity.SetTag("db.query.summary", querySummary);
+
+ SetConnectionTags(activity, connectionId);
+
+ if (command != null)
+ {
+ if (command.TryGetValue("lsid", out var lsid))
+ {
+ // Materialize the lsid to avoid accessing disposed RawBsonDocument later
+ var materializedLsid = lsid.IsBsonDocument
+ ? new BsonDocument(lsid.AsBsonDocument)
+ : lsid;
+ activity.SetTag("db.mongodb.lsid", materializedLsid);
+ }
+
+ if (command.TryGetValue("txnNumber", out var txnNumber))
+ {
+ activity.SetTag("db.mongodb.txn_number", txnNumber.ToInt64());
+ }
+
+ if (queryTextMaxLength > 0)
+ {
+ SetQueryText(activity, command, queryTextMaxLength);
+ }
+ }
+ }
+
+ return activity;
+ }
+
+ internal static void RecordException(Activity activity, Exception exception)
+ {
+ if (activity == null)
+ {
+ return;
+ }
+
+ activity.SetTag("exception.type", exception.GetType().FullName);
+ activity.SetTag("exception.message", exception.Message);
+ if (exception.StackTrace != null)
+ {
+ activity.SetTag("exception.stacktrace", exception.StackTrace);
+ }
+ activity.SetStatus(ActivityStatusCode.Error);
+ }
+
+ private static void SetConnectionTags(Activity activity, ConnectionId connectionId)
+ {
+ var endPoint = connectionId?.ServerId?.EndPoint;
+ switch (endPoint)
+ {
+ case IPEndPoint ipEndPoint:
+ activity.SetTag("server.address", ipEndPoint.Address.ToString());
+ activity.SetTag("server.port", (long)ipEndPoint.Port);
+ activity.SetTag("network.transport", "tcp");
+ break;
+ case DnsEndPoint dnsEndPoint:
+ activity.SetTag("server.address", dnsEndPoint.Host);
+ activity.SetTag("server.port", (long)dnsEndPoint.Port);
+ activity.SetTag("network.transport", "tcp");
+ break;
+#if NET5_0_OR_GREATER || NETCOREAPP3_0_OR_GREATER
+ case UnixDomainSocketEndPoint unixEndPoint:
+ activity.SetTag("network.transport", "unix");
+ activity.SetTag("server.address", unixEndPoint.ToString());
+ break;
+#endif
+ }
+
+ if (connectionId != null)
+ {
+ if (connectionId.LongServerValue.HasValue)
+ {
+ activity.SetTag("db.mongodb.server_connection_id", connectionId.LongServerValue.Value);
+ }
+ activity.SetTag("db.mongodb.driver_connection_id", connectionId.LongLocalValue);
+ }
+ }
+
+ private static void SetQueryText(Activity activity, BsonDocument command, int maxLength)
+ {
+ var commandToLog = FilterSensitiveData(command);
+ var commandText = commandToLog.ToJson();
+
+ if (commandText.Length > maxLength)
+ {
+ commandText = commandText.Substring(0, maxLength);
+ }
+
+ activity?.SetTag("db.query.text", commandText);
+ }
+
+ private static BsonDocument FilterSensitiveData(BsonDocument command)
+ {
+ var filtered = new BsonDocument(command);
+ filtered.Remove("lsid");
+ filtered.Remove("$db");
+ filtered.Remove("$clusterTime");
+ filtered.Remove("signature");
+ return filtered;
+ }
+
+ private static string ExtractCollectionName(BsonDocument command)
+ {
+ if (command == null) return null;
+
+ var firstElement = command.GetElement(0);
+ if (firstElement.Value.IsString)
+ {
+ var value = firstElement.Value.AsString;
+ if (value != "1" && value != "admin" && !string.IsNullOrEmpty(value))
+ {
+ return value;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/src/MongoDB.Driver/OperationContext.cs b/src/MongoDB.Driver/OperationContext.cs
index 7d0ce583df8..fea7c6f13da 100644
--- a/src/MongoDB.Driver/OperationContext.cs
+++ b/src/MongoDB.Driver/OperationContext.cs
@@ -51,6 +51,12 @@ internal OperationContext(IClock clock, long initialTimestamp, TimeSpan? timeout
public OperationContext RootContext { get; private init; }
+ // OpenTelemetry operation metadata
+ internal string OperationName { get; init; }
+ internal string DatabaseName { get; init; }
+ internal string CollectionName { get; init; }
+ internal bool IsTracingEnabled { get; init; }
+
public TimeSpan RemainingTimeout
{
get
@@ -213,5 +219,17 @@ public OperationContext WithTimeout(TimeSpan timeout)
RootContext = RootContext
};
}
+
+ internal OperationContext WithOperationMetadata(string operationName, string databaseName, string collectionName, bool isTracingEnabled)
+ {
+ return new OperationContext(Clock, InitialTimestamp, Timeout, CancellationToken)
+ {
+ RootContext = RootContext,
+ OperationName = operationName,
+ DatabaseName = databaseName,
+ CollectionName = collectionName,
+ IsTracingEnabled = isTracingEnabled
+ };
+ }
}
}
diff --git a/src/MongoDB.Driver/OperationExecutor.cs b/src/MongoDB.Driver/OperationExecutor.cs
index 929c28b6063..061e18b083f 100644
--- a/src/MongoDB.Driver/OperationExecutor.cs
+++ b/src/MongoDB.Driver/OperationExecutor.cs
@@ -14,6 +14,7 @@
*/
using System;
+using System.Diagnostics;
using System.Threading.Tasks;
using MongoDB.Driver.Core;
using MongoDB.Driver.Core.Bindings;
@@ -50,8 +51,41 @@ public TResult ExecuteReadOperation(
Ensure.IsNotNull(readPreference, nameof(readPreference));
ThrowIfDisposed();
- using var binding = CreateReadBinding(session, readPreference, allowChannelPinning);
- return operation.Execute(operationContext, binding);
+ using var activityScope = TransactionActivityScope.CreateIfNeeded(session);
+ using var activity = operationContext.IsTracingEnabled
+ ? MongoTelemetry.StartOperationActivity(
+ operationContext.OperationName,
+ operationContext.DatabaseName,
+ operationContext.CollectionName)
+ : null;
+
+ try
+ {
+ using var binding = CreateReadBinding(session, readPreference, allowChannelPinning);
+ var result = operation.Execute(operationContext, binding);
+ activity?.SetStatus(ActivityStatusCode.Ok);
+ return result;
+ }
+ catch (Exception ex)
+ {
+ // Only record exceptions that originate at the operation level
+ // Command-level exceptions (MongoCommandException, MongoWriteException, etc.)
+ // are already recorded by CommandEventHelper on the command span
+ if (activity != null)
+ {
+ if (!IsCommandLevelException(ex))
+ {
+ MongoTelemetry.RecordException(activity, ex);
+ }
+ else
+ {
+ // For command-level exceptions, only set error status without recording details
+ activity.SetStatus(ActivityStatusCode.Error);
+ }
+ }
+
+ throw;
+ }
}
public async Task ExecuteReadOperationAsync(
@@ -67,8 +101,41 @@ public async Task ExecuteReadOperationAsync(
Ensure.IsNotNull(readPreference, nameof(readPreference));
ThrowIfDisposed();
- using var binding = CreateReadBinding(session, readPreference, allowChannelPinning);
- return await operation.ExecuteAsync(operationContext, binding).ConfigureAwait(false);
+ using var activityScope = TransactionActivityScope.CreateIfNeeded(session);
+ using var activity = operationContext.IsTracingEnabled
+ ? MongoTelemetry.StartOperationActivity(
+ operationContext.OperationName,
+ operationContext.DatabaseName,
+ operationContext.CollectionName)
+ : null;
+
+ try
+ {
+ using var binding = CreateReadBinding(session, readPreference, allowChannelPinning);
+ var result = await operation.ExecuteAsync(operationContext, binding).ConfigureAwait(false);
+ activity?.SetStatus(ActivityStatusCode.Ok);
+ return result;
+ }
+ catch (Exception ex)
+ {
+ // Only record exceptions that originate at the operation level
+ // Command-level exceptions (MongoCommandException, MongoWriteException, etc.)
+ // are already recorded by CommandEventHelper on the command span
+ if (activity != null)
+ {
+ if (!IsCommandLevelException(ex))
+ {
+ MongoTelemetry.RecordException(activity, ex);
+ }
+ else
+ {
+ // For command-level exceptions, only set error status without recording details
+ activity.SetStatus(ActivityStatusCode.Error);
+ }
+ }
+
+ throw;
+ }
}
public TResult ExecuteWriteOperation