From abfb239853593ebc947bf84ce1d08f5a939dfde3 Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Fri, 7 Feb 2025 11:23:25 -0500 Subject: [PATCH 01/17] inject dbm trace comment --- .../datadog-plugin-mongodb-core/src/index.js | 6 ++-- packages/dd-trace/src/plugins/database.js | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/src/index.js b/packages/datadog-plugin-mongodb-core/src/index.js index 076d65917b5..1bae5817b8c 100644 --- a/packages/datadog-plugin-mongodb-core/src/index.js +++ b/packages/datadog-plugin-mongodb-core/src/index.js @@ -11,8 +11,9 @@ class MongodbCorePlugin extends DatabasePlugin { start ({ ns, ops, options = {}, name }) { const query = getQuery(ops) const resource = truncate(getResource(this, ns, query, name)) - this.startSpan(this.operationName(), { - service: this.serviceName({ pluginConfig: this.config }), + const service = this.serviceName({ pluginConfig: this.config }) + const span = this.startSpan(this.operationName(), { + service, resource, type: 'mongodb', kind: 'client', @@ -24,6 +25,7 @@ class MongodbCorePlugin extends DatabasePlugin { 'out.port': options.port } }) + ops = this.injectDbmCommand(span, ops, service) } getPeerService (tags) { diff --git a/packages/dd-trace/src/plugins/database.js b/packages/dd-trace/src/plugins/database.js index 9296ae46d6d..be41e588ea9 100644 --- a/packages/dd-trace/src/plugins/database.js +++ b/packages/dd-trace/src/plugins/database.js @@ -2,6 +2,8 @@ const StoragePlugin = require('./storage') const { PEER_SERVICE_KEY, PEER_SERVICE_SOURCE_KEY } = require('../constants') +const { re } = require('semver') +const { type } = require('os') class DatabasePlugin extends StoragePlugin { static get operation () { return 'query' } @@ -82,6 +84,40 @@ class DatabasePlugin extends StoragePlugin { } } + injectDbmCommand (span, command, serviceName) { + const mode = this.config.dbmPropagationMode + + if (mode === 'disabled') { + return command + } + + let dbmTraceComment = '' + + const dbmService = this.getDbmServiceName(span, serviceName) + const servicePropagation = this.createDBMPropagationCommentService(dbmService, span) + + if (mode === 'service') { + dbmTraceComment = `${servicePropagation}` + } else if (mode === 'full') { + span.setTag('_dd.dbm_trace_injected', 'true') + const traceparent = span._spanContext.toTraceparent() + dbmTraceComment = `${servicePropagation},traceparent='${traceparent}'` + } + + if (command.comment) { + // if the command already has a comment, append the dbm trace comment + if (typeof command.comment === 'string') { + command.comment += `,${dbmTraceComment}` + } else if (Array.isArray(command.comment)) { + command.comment.push(dbmTraceComment) + } // do nothing if the comment is not a string or an array + } else { + command.comment = dbmTraceComment + } + + return command + } + maybeTruncate (query) { const maxLength = typeof this.config.truncate === 'number' ? this.config.truncate From 2f887c5f420cc895621009b2d17bf38faacab962 Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Fri, 7 Feb 2025 15:58:49 -0500 Subject: [PATCH 02/17] add service mode test --- .../test/core.spec.js | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/packages/datadog-plugin-mongodb-core/test/core.spec.js b/packages/datadog-plugin-mongodb-core/test/core.spec.js index 13a346077cf..1f3ed4c88e9 100644 --- a/packages/datadog-plugin-mongodb-core/test/core.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/core.spec.js @@ -397,6 +397,51 @@ describe('Plugin', () => { } ) }) + + describe('with dbmPropagationMode service', () => { + before(() => { + return agent.load('mongodb-core', { service: 'custom', dbmPropagationMode: 'service' }) + }) + + after(() => { + return agent.close({ ritmReset: false }) + }) + + beforeEach(done => { + const Server = getServer() + + server = new Server({ + host: '127.0.0.1', + port: 27017, + reconnect: false + }) + + server.on('connect', () => done()) + server.on('error', done) + + server.connect() + }) + + it('should be contain comment in command', done => { + agent + .use(traces => { + expect(traces[0][0]).to.have.property('name', expectedSchema.outbound.opName) + }) + .then(done) + .catch(done) + + + const command = server.insert(`test.${collection}`, [{ a: 1 }], () => { + try { + expect(command.comment).to.equal('dddb=\'db\',dddbs=\'serviced\',dde=\'tester\',ddh=\'127.0.0.1\',' + + `ddps='test',ddpv='${ddpv}'`) + } catch (e) { + done(e) + } + done() + }) + }) + }) }) }) }) From f84e138a86199ba593b9626cc59be147de2e5028 Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Mon, 10 Feb 2025 20:12:38 +0000 Subject: [PATCH 03/17] add unit test to verify both full and service mode --- .../test/core.spec.js | 45 -------- .../test/mongodb.spec.js | 109 ++++++++++++++++++ 2 files changed, 109 insertions(+), 45 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/test/core.spec.js b/packages/datadog-plugin-mongodb-core/test/core.spec.js index 1f3ed4c88e9..13a346077cf 100644 --- a/packages/datadog-plugin-mongodb-core/test/core.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/core.spec.js @@ -397,51 +397,6 @@ describe('Plugin', () => { } ) }) - - describe('with dbmPropagationMode service', () => { - before(() => { - return agent.load('mongodb-core', { service: 'custom', dbmPropagationMode: 'service' }) - }) - - after(() => { - return agent.close({ ritmReset: false }) - }) - - beforeEach(done => { - const Server = getServer() - - server = new Server({ - host: '127.0.0.1', - port: 27017, - reconnect: false - }) - - server.on('connect', () => done()) - server.on('error', done) - - server.connect() - }) - - it('should be contain comment in command', done => { - agent - .use(traces => { - expect(traces[0][0]).to.have.property('name', expectedSchema.outbound.opName) - }) - .then(done) - .catch(done) - - - const command = server.insert(`test.${collection}`, [{ a: 1 }], () => { - try { - expect(command.comment).to.equal('dddb=\'db\',dddbs=\'serviced\',dde=\'tester\',ddh=\'127.0.0.1\',' + - `ddps='test',ddpv='${ddpv}'`) - } catch (e) { - done(e) - } - done() - }) - }) - }) }) }) }) diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index 0e16a3fd71a..0d4495d9bf9 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -1,9 +1,13 @@ 'use strict' +const sinon = require('sinon') const semver = require('semver') const agent = require('../../dd-trace/test/plugins/agent') const { expectedSchema, rawExpectedSchema } = require('./naming') +const MongodbCorePlugin = require('../../datadog-plugin-mongodb-core/src/index') +const ddpv = require('mocha/package.json').version + const withTopologies = fn => { const isOldNode = semver.satisfies(process.version, '<=14') const range = isOldNode ? '>=2 <6' : '>=2' // TODO: remove when 3.x support is removed. @@ -44,6 +48,8 @@ describe('Plugin', () => { let collection let db let BSON + let injectDbmCommandSpy + let clock describe('mongodb-core', () => { withTopologies(createClient => { @@ -334,6 +340,109 @@ describe('Plugin', () => { } ) }) + + describe('with dbmPropagationMode service', () => { + before(() => { + return agent.load('mongodb-core', { + dbmPropagationMode: 'service', + }) + }) + + after(() => { + return agent.close({ ritmReset: false }) + }) + + beforeEach(async () => { + client = await createClient() + db = client.db('test') + collection = db.collection(collectionName) + + sinon.restore() + injectDbmCommandSpy = sinon.spy(MongodbCorePlugin.prototype, 'injectDbmCommand') + }) + + afterEach(() => { + injectDbmCommandSpy?.restore() + }) + + it('DBM propagation should inject service mode as comment', done => { + agent + .use(traces => { + const span = traces[0][0] + + expect(injectDbmCommandSpy.calledOnce).to.be.true + const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue + expect(instrumentedCommand).to.have.property('comment') + expect(instrumentedCommand.comment).to.equal( + `dddb='${encodeURIComponent(span.meta['db.name'])}',` + + `dddbs='test-mongodb',` + + `dde='tester',` + + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + + `ddps='${encodeURIComponent(span.meta.service)}',` + + `ddpv='${ddpv}',` + + `ddprs='${encodeURIComponent(span.meta['peer.service'])}'` + ); + }) + .then(done) + .catch(done) + + collection.insertOne({ a: 1 }, {}, () => {}) + }) + }) + + describe('with dbmPropagationMode full', () => { + before(() => { + return agent.load('mongodb-core', { + dbmPropagationMode: 'full', + }) + }) + + after(() => { + return agent.close({ ritmReset: false }) + }) + + beforeEach(async () => { + client = await createClient() + db = client.db('test') + collection = db.collection(collectionName) + + clock = sinon.useFakeTimers(new Date()) + injectDbmCommandSpy = sinon.spy(MongodbCorePlugin.prototype, 'injectDbmCommand') + }) + + afterEach(() => { + clock?.restore() + injectDbmCommandSpy?.restore() + }) + + it('DBM propagation should inject full mode with traceparent as comment', done => { + agent + .use(traces => { + const span = traces[0][0] + const expectedTimePrefix = Math.floor(clock.now / 1000).toString(16).padStart(8, '0').padEnd(16, '0') + const traceId = expectedTimePrefix +span.trace_id.toString(16).padStart(16, '0') + const spanId = span.span_id.toString(16).padStart(16, '0') + + expect(injectDbmCommandSpy.calledOnce).to.be.true + const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue + expect(instrumentedCommand).to.have.property('comment') + expect(instrumentedCommand.comment).to.equal( + `dddb='${encodeURIComponent(span.meta['db.name'])}',` + + `dddbs='test-mongodb',` + + `dde='tester',` + + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + + `ddps='${encodeURIComponent(span.meta.service)}',` + + `ddpv='${ddpv}',` + + `ddprs='${encodeURIComponent(span.meta['peer.service'])}',`+ + `traceparent='00-${traceId}-${spanId}-00'` + ); + }) + .then(done) + .catch(done) + + collection.insertOne({ a: 1 }, {}, () => {}) + }) + }) }) }) }) From a2e6c25c3ea0a5434c4f05da0117b8a297761f0a Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Mon, 10 Feb 2025 20:20:25 +0000 Subject: [PATCH 04/17] update test --- packages/datadog-plugin-mongodb-core/test/mongodb.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index 0d4495d9bf9..93ede71b1ba 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -370,7 +370,7 @@ describe('Plugin', () => { .use(traces => { const span = traces[0][0] - expect(injectDbmCommandSpy.calledOnce).to.be.true + expect(injectDbmCommandSpy.called).to.be.true const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue expect(instrumentedCommand).to.have.property('comment') expect(instrumentedCommand.comment).to.equal( @@ -423,7 +423,7 @@ describe('Plugin', () => { const traceId = expectedTimePrefix +span.trace_id.toString(16).padStart(16, '0') const spanId = span.span_id.toString(16).padStart(16, '0') - expect(injectDbmCommandSpy.calledOnce).to.be.true + expect(injectDbmCommandSpy.called).to.be.true const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue expect(instrumentedCommand).to.have.property('comment') expect(instrumentedCommand.comment).to.equal( From cab568b4e69e071549771af535fea073a73c225d Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Mon, 10 Feb 2025 20:32:19 +0000 Subject: [PATCH 05/17] fix lint --- .../test/mongodb.spec.js | 24 +++++++++---------- packages/dd-trace/src/plugins/database.js | 2 -- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index 93ede71b1ba..1c709954c93 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -344,7 +344,7 @@ describe('Plugin', () => { describe('with dbmPropagationMode service', () => { before(() => { return agent.load('mongodb-core', { - dbmPropagationMode: 'service', + dbmPropagationMode: 'service' }) }) @@ -375,25 +375,25 @@ describe('Plugin', () => { expect(instrumentedCommand).to.have.property('comment') expect(instrumentedCommand.comment).to.equal( `dddb='${encodeURIComponent(span.meta['db.name'])}',` + - `dddbs='test-mongodb',` + - `dde='tester',` + + 'dddbs=\'test-mongodb\',' + + 'dde=\'tester\',' + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + `ddps='${encodeURIComponent(span.meta.service)}',` + `ddpv='${ddpv}',` + `ddprs='${encodeURIComponent(span.meta['peer.service'])}'` - ); + ) }) .then(done) .catch(done) - collection.insertOne({ a: 1 }, {}, () => {}) + collection.insertOne({ a: 1 }, {}, () => {}) }) }) describe('with dbmPropagationMode full', () => { before(() => { return agent.load('mongodb-core', { - dbmPropagationMode: 'full', + dbmPropagationMode: 'full' }) }) @@ -420,7 +420,7 @@ describe('Plugin', () => { .use(traces => { const span = traces[0][0] const expectedTimePrefix = Math.floor(clock.now / 1000).toString(16).padStart(8, '0').padEnd(16, '0') - const traceId = expectedTimePrefix +span.trace_id.toString(16).padStart(16, '0') + const traceId = expectedTimePrefix + span.trace_id.toString(16).padStart(16, '0') const spanId = span.span_id.toString(16).padStart(16, '0') expect(injectDbmCommandSpy.called).to.be.true @@ -428,18 +428,18 @@ describe('Plugin', () => { expect(instrumentedCommand).to.have.property('comment') expect(instrumentedCommand.comment).to.equal( `dddb='${encodeURIComponent(span.meta['db.name'])}',` + - `dddbs='test-mongodb',` + - `dde='tester',` + + 'dddbs=\'test-mongodb\',' + + 'dde=\'tester\',' + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + `ddps='${encodeURIComponent(span.meta.service)}',` + `ddpv='${ddpv}',` + - `ddprs='${encodeURIComponent(span.meta['peer.service'])}',`+ + `ddprs='${encodeURIComponent(span.meta['peer.service'])}',` + `traceparent='00-${traceId}-${spanId}-00'` - ); + ) }) .then(done) .catch(done) - + collection.insertOne({ a: 1 }, {}, () => {}) }) }) diff --git a/packages/dd-trace/src/plugins/database.js b/packages/dd-trace/src/plugins/database.js index be41e588ea9..a42ffb66f1c 100644 --- a/packages/dd-trace/src/plugins/database.js +++ b/packages/dd-trace/src/plugins/database.js @@ -2,8 +2,6 @@ const StoragePlugin = require('./storage') const { PEER_SERVICE_KEY, PEER_SERVICE_SOURCE_KEY } = require('../constants') -const { re } = require('semver') -const { type } = require('os') class DatabasePlugin extends StoragePlugin { static get operation () { return 'query' } From f14dd0f82c03999a7b782bd12edc8eb3ab01300a Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Mon, 10 Feb 2025 20:53:22 +0000 Subject: [PATCH 06/17] use find query --- packages/datadog-plugin-mongodb-core/test/mongodb.spec.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index 1c709954c93..9c17e0c6fe4 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -440,7 +440,9 @@ describe('Plugin', () => { .then(done) .catch(done) - collection.insertOne({ a: 1 }, {}, () => {}) + collection.find({ + _id: Buffer.from('1234') + }).toArray() }) }) }) From d4048c449c38b16740e832c959d21f8b13c79962 Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Mon, 10 Feb 2025 21:15:13 +0000 Subject: [PATCH 07/17] fix timeout --- .../test/mongodb.spec.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index 9c17e0c6fe4..8fa947eac89 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -386,7 +386,11 @@ describe('Plugin', () => { .then(done) .catch(done) - collection.insertOne({ a: 1 }, {}, () => {}) + collection.find({ + _id: Buffer.from('1234') + }).toArray() + .then(done) + .catch(done) }) }) @@ -440,9 +444,11 @@ describe('Plugin', () => { .then(done) .catch(done) - collection.find({ - _id: Buffer.from('1234') - }).toArray() + collection.find({ + _id: Buffer.from('1234') + }).toArray() + .then(done) + .catch(done) }) }) }) From 8c06bdc32e5ce46235bcecd37e88e72c00a4943c Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Mon, 10 Feb 2025 21:17:11 +0000 Subject: [PATCH 08/17] remove done --- packages/datadog-plugin-mongodb-core/test/mongodb.spec.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index 8fa947eac89..ce5cdaa6c8a 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -389,8 +389,6 @@ describe('Plugin', () => { collection.find({ _id: Buffer.from('1234') }).toArray() - .then(done) - .catch(done) }) }) @@ -447,8 +445,6 @@ describe('Plugin', () => { collection.find({ _id: Buffer.from('1234') }).toArray() - .then(done) - .catch(done) }) }) }) From a129ed3d781d9f1301210784f11aae388eb39a46 Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Mon, 10 Feb 2025 22:31:54 +0000 Subject: [PATCH 09/17] add tests to mongodb-core --- .../test/core.spec.js | 118 ++++++++++++++++++ .../test/mongodb.spec.js | 13 +- 2 files changed, 123 insertions(+), 8 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/test/core.spec.js b/packages/datadog-plugin-mongodb-core/test/core.spec.js index 13a346077cf..e00d5c927d8 100644 --- a/packages/datadog-plugin-mongodb-core/test/core.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/core.spec.js @@ -1,10 +1,14 @@ 'use strict' +const sinon = require('sinon') const semver = require('semver') const agent = require('../../dd-trace/test/plugins/agent') const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants') const { expectedSchema, rawExpectedSchema } = require('./naming') +const MongodbCorePlugin = require('../../datadog-plugin-mongodb-core/src/index') +const ddpv = require('mocha/package.json').version + const withTopologies = fn => { withVersions('mongodb-core', ['mongodb-core', 'mongodb'], '<4', (version, moduleName) => { describe('using the server topology', () => { @@ -29,6 +33,7 @@ describe('Plugin', () => { let id let tracer let collection + let injectDbmCommandSpy describe('mongodb-core (core)', () => { withTopologies(getServer => { @@ -397,6 +402,119 @@ describe('Plugin', () => { } ) }) + + describe('with dbmPropagationMode service', () => { + before(() => { + return agent.load('mongodb-core', { dbmPropagationMode: 'service' }) + }) + + after(() => { + return agent.close({ ritmReset: false }) + }) + + beforeEach(done => { + const Server = getServer() + + server = new Server({ + host: '127.0.0.1', + port: 27017, + reconnect: false + }) + + server.on('connect', () => done()) + server.on('error', done) + + server.connect() + + injectDbmCommandSpy = sinon.spy(MongodbCorePlugin.prototype, 'injectDbmCommand') + }) + + afterEach(() => { + injectDbmCommandSpy?.restore() + }) + + it('DBM propagation should inject service mode as comment', done => { + agent + .use(traces => { + const span = traces[0][0] + + expect(injectDbmCommandSpy.called).to.be.true + const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue + expect(instrumentedCommand).to.have.property('comment') + expect(instrumentedCommand.comment).to.equal( + `dddb='${encodeURIComponent(span.meta['db.name'])}',` + + 'dddbs=\'test-mongodb\',' + + 'dde=\'tester\',' + + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + + `ddps='${encodeURIComponent(span.meta.service)}',` + + `ddpv='${ddpv}',` + + `ddprs='${encodeURIComponent(span.meta['peer.service'])}'` + ) + }) + .then(done) + .catch(done) + + server.insert(`test.${collection}`, [{ a: 1 }], () => {}) + }) + }) + + describe('with dbmPropagationMode full', () => { + before(() => { + return agent.load('mongodb-core', { dbmPropagationMode: 'service' }) + }) + + after(() => { + return agent.close({ ritmReset: false }) + }) + + beforeEach(done => { + const Server = getServer() + + server = new Server({ + host: '127.0.0.1', + port: 27017, + reconnect: false + }) + + server.on('connect', () => done()) + server.on('error', done) + + server.connect() + + injectDbmCommandSpy = sinon.spy(MongodbCorePlugin.prototype, 'injectDbmCommand') + }) + + afterEach(() => { + injectDbmCommandSpy?.restore() + }) + + it('DBM propagation should inject full mode with traceparent as comment', done => { + agent + .use(traces => { + const span = traces[0][0] + const traceId = span.meta['_dd.p.tid'] + span.trace_id.toString(16).padStart(16, '0') + const spanId = span.span_id.toString(16).padStart(16, '0') + + expect(injectDbmCommandSpy.called).to.be.true + const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue + expect(instrumentedCommand).to.have.property('comment') + expect(instrumentedCommand.comment).to.equal( + `dddb='${encodeURIComponent(span.meta['db.name'])}',` + + 'dddbs=\'test-mongodb\',' + + 'dde=\'tester\',' + + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + + `ddps='${encodeURIComponent(span.meta.service)}',` + + `ddpv='${ddpv}',` + + `ddprs='${encodeURIComponent(span.meta['peer.service'])}',` + + `traceparent='00-${traceId}-${spanId}-00'` + ) + }) + .then(done) + .catch(done) + + server.insert(`test.${collection}`, [{ a: 1 }], () => {}) + }) + }) }) }) }) diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index ce5cdaa6c8a..ac5b3b30638 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -49,7 +49,6 @@ describe('Plugin', () => { let db let BSON let injectDbmCommandSpy - let clock describe('mongodb-core', () => { withTopologies(createClient => { @@ -342,7 +341,8 @@ describe('Plugin', () => { }) describe('with dbmPropagationMode service', () => { - before(() => { + before(function () { + this.timeout(10000) return agent.load('mongodb-core', { dbmPropagationMode: 'service' }) @@ -357,7 +357,6 @@ describe('Plugin', () => { db = client.db('test') collection = db.collection(collectionName) - sinon.restore() injectDbmCommandSpy = sinon.spy(MongodbCorePlugin.prototype, 'injectDbmCommand') }) @@ -393,7 +392,8 @@ describe('Plugin', () => { }) describe('with dbmPropagationMode full', () => { - before(() => { + before(function () { + this.timeout(10000) return agent.load('mongodb-core', { dbmPropagationMode: 'full' }) @@ -408,12 +408,10 @@ describe('Plugin', () => { db = client.db('test') collection = db.collection(collectionName) - clock = sinon.useFakeTimers(new Date()) injectDbmCommandSpy = sinon.spy(MongodbCorePlugin.prototype, 'injectDbmCommand') }) afterEach(() => { - clock?.restore() injectDbmCommandSpy?.restore() }) @@ -421,8 +419,7 @@ describe('Plugin', () => { agent .use(traces => { const span = traces[0][0] - const expectedTimePrefix = Math.floor(clock.now / 1000).toString(16).padStart(8, '0').padEnd(16, '0') - const traceId = expectedTimePrefix + span.trace_id.toString(16).padStart(16, '0') + const traceId = span.meta['_dd.p.tid'] + span.trace_id.toString(16).padStart(16, '0') const spanId = span.span_id.toString(16).padStart(16, '0') expect(injectDbmCommandSpy.called).to.be.true From 2bc6ccb7af5d4d447c9a43b658d94e5d1ac5a2ce Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Mon, 10 Feb 2025 22:36:46 +0000 Subject: [PATCH 10/17] fix service mode full --- packages/datadog-plugin-mongodb-core/test/core.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/datadog-plugin-mongodb-core/test/core.spec.js b/packages/datadog-plugin-mongodb-core/test/core.spec.js index e00d5c927d8..322345c991e 100644 --- a/packages/datadog-plugin-mongodb-core/test/core.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/core.spec.js @@ -460,7 +460,7 @@ describe('Plugin', () => { describe('with dbmPropagationMode full', () => { before(() => { - return agent.load('mongodb-core', { dbmPropagationMode: 'service' }) + return agent.load('mongodb-core', { dbmPropagationMode: 'full' }) }) after(() => { From 1494f45279dbb0da3ae170c69a0b417a246a0f34 Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Mon, 10 Feb 2025 22:43:25 +0000 Subject: [PATCH 11/17] remove custom timeout --- packages/datadog-plugin-mongodb-core/test/mongodb.spec.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index ac5b3b30638..db6ee8ffeec 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -341,8 +341,7 @@ describe('Plugin', () => { }) describe('with dbmPropagationMode service', () => { - before(function () { - this.timeout(10000) + before(() => { return agent.load('mongodb-core', { dbmPropagationMode: 'service' }) @@ -392,8 +391,7 @@ describe('Plugin', () => { }) describe('with dbmPropagationMode full', () => { - before(function () { - this.timeout(10000) + before(() => { return agent.load('mongodb-core', { dbmPropagationMode: 'full' }) From fecc4f231d5ee5dd930023d3e45e5c37378db28c Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Tue, 11 Feb 2025 14:38:56 -0500 Subject: [PATCH 12/17] Update packages/dd-trace/src/plugins/database.js Co-authored-by: Bryan English --- packages/dd-trace/src/plugins/database.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dd-trace/src/plugins/database.js b/packages/dd-trace/src/plugins/database.js index a42ffb66f1c..e03b454d4c5 100644 --- a/packages/dd-trace/src/plugins/database.js +++ b/packages/dd-trace/src/plugins/database.js @@ -95,7 +95,7 @@ class DatabasePlugin extends StoragePlugin { const servicePropagation = this.createDBMPropagationCommentService(dbmService, span) if (mode === 'service') { - dbmTraceComment = `${servicePropagation}` + dbmTraceComment = servicePropagation } else if (mode === 'full') { span.setTag('_dd.dbm_trace_injected', 'true') const traceparent = span._spanContext.toTraceparent() From 145b3bc8b6f92982203eedfe8a993d0b5529dd4d Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Tue, 11 Feb 2025 20:22:47 +0000 Subject: [PATCH 13/17] merge duplicate code --- packages/dd-trace/src/plugins/database.js | 31 ++++++++++------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/dd-trace/src/plugins/database.js b/packages/dd-trace/src/plugins/database.js index e03b454d4c5..1328b98f46a 100644 --- a/packages/dd-trace/src/plugins/database.js +++ b/packages/dd-trace/src/plugins/database.js @@ -63,43 +63,40 @@ class DatabasePlugin extends StoragePlugin { return tracerService } - injectDbmQuery (span, query, serviceName, isPreparedStatement = false) { + createDbmComment (span, serviceName, isPreparedStatement = false) { const mode = this.config.dbmPropagationMode const dbmService = this.getDbmServiceName(span, serviceName) if (mode === 'disabled') { - return query + return null } const servicePropagation = this.createDBMPropagationCommentService(dbmService, span) if (isPreparedStatement || mode === 'service') { - return `/*${servicePropagation}*/ ${query}` + return servicePropagation } else if (mode === 'full') { span.setTag('_dd.dbm_trace_injected', 'true') const traceparent = span._spanContext.toTraceparent() - return `/*${servicePropagation},traceparent='${traceparent}'*/ ${query}` + return `${servicePropagation},traceparent='${traceparent}'` } } - injectDbmCommand (span, command, serviceName) { - const mode = this.config.dbmPropagationMode + injectDbmQuery (span, query, serviceName, isPreparedStatement = false) { + const dbmTraceComment = this.createDbmComment(span, serviceName, isPreparedStatement) - if (mode === 'disabled') { - return command + if (!dbmTraceComment) { + return query } - let dbmTraceComment = '' + return `/*${dbmTraceComment}*/ ${query}` + } - const dbmService = this.getDbmServiceName(span, serviceName) - const servicePropagation = this.createDBMPropagationCommentService(dbmService, span) + injectDbmCommand (span, command, serviceName) { + const dbmTraceComment = this.createDbmComment(span, serviceName) - if (mode === 'service') { - dbmTraceComment = servicePropagation - } else if (mode === 'full') { - span.setTag('_dd.dbm_trace_injected', 'true') - const traceparent = span._spanContext.toTraceparent() - dbmTraceComment = `${servicePropagation},traceparent='${traceparent}'` + if (!dbmTraceComment) { + return command } if (command.comment) { From e224aae50e13a48804618b25fa0cc9a7e80c6653 Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Wed, 12 Feb 2025 22:04:07 +0000 Subject: [PATCH 14/17] add tests --- docker-compose.yml | 2 +- .../datadog-plugin-mongodb-core/src/index.js | 24 +++++++ .../test/mongodb.spec.js | 65 +++++++++++++++++++ packages/dd-trace/src/plugins/database.js | 21 ------ 4 files changed, 90 insertions(+), 22 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 81bdd3c2032..cebd93ba020 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,7 +37,7 @@ services: ports: - "127.0.0.1:6379:6379" mongo: - image: circleci/mongo:3.6 + image: circleci/mongo:4.4 platform: linux/amd64 ports: - "127.0.0.1:27017:27017" diff --git a/packages/datadog-plugin-mongodb-core/src/index.js b/packages/datadog-plugin-mongodb-core/src/index.js index 1bae5817b8c..f4e4d94a82d 100644 --- a/packages/datadog-plugin-mongodb-core/src/index.js +++ b/packages/datadog-plugin-mongodb-core/src/index.js @@ -36,6 +36,30 @@ class MongodbCorePlugin extends DatabasePlugin { } return super.getPeerService(tags) } + + injectDbmCommand (span, command, serviceName) { + const dbmTraceComment = this.createDbmComment(span, serviceName) + + if (!dbmTraceComment) { + return command + } + + // create a copy of the command to avoid mutating the original + const dbmTracedCommand = { ...command } + + if (dbmTracedCommand.comment) { + // if the command already has a comment, append the dbm trace comment + if (typeof dbmTracedCommand.comment === 'string') { + dbmTracedCommand.comment += `,${dbmTraceComment}` + } else if (Array.isArray(command.comment)) { + dbmTracedCommand.comment.push(dbmTraceComment) + } // do nothing if the comment is not a string or an array + } else { + dbmTracedCommand.comment = dbmTraceComment + } + + return dbmTracedCommand + } } function sanitizeBigInt (data) { diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index db6ee8ffeec..baee2862628 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -388,6 +388,71 @@ describe('Plugin', () => { _id: Buffer.from('1234') }).toArray() }) + + it('should append DBM propagation to existing str comment', done => { + agent + .use(traces => { + const span = traces[0][0] + + expect(injectDbmCommandSpy.called).to.be.true + const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue + expect(instrumentedCommand).to.have.property('comment') + expect(instrumentedCommand.comment).to.equal( + 'find test,' + + `dddb='${encodeURIComponent(span.meta['db.name'])}',` + + 'dddbs=\'test-mongodb\',' + + 'dde=\'tester\',' + + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + + `ddps='${encodeURIComponent(span.meta.service)}',` + + `ddpv='${ddpv}',` + + `ddprs='${encodeURIComponent(span.meta['peer.service'])}'` + ) + }) + .then(done) + .catch(done) + + collection.find( + { + _id: Buffer.from('1234') + }, + { + comment: 'find test' + } + ).toArray() + }) + + it('should append DBM propagation to existing array comment', done => { + agent + .use(traces => { + const span = traces[0][0] + + expect(injectDbmCommandSpy.called).to.be.true + const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue + expect(instrumentedCommand).to.have.property('comment') + expect(instrumentedCommand.comment).to.be.an('array') + expect(instrumentedCommand.comment).to.equal([ + 'find test', + `dddb='${encodeURIComponent(span.meta['db.name'])}',` + + 'dddbs=\'test-mongodb\',' + + 'dde=\'tester\',' + + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + + `ddps='${encodeURIComponent(span.meta.service)}',` + + `ddpv='${ddpv}',` + + `ddprs='${encodeURIComponent(span.meta['peer.service'])}'` + ]) + }) + .then(done) + .catch(done) + + collection.find( + { + _id: Buffer.from('1234') + }, + { + comment: ['find test'] + } + ).toArray() + }) }) describe('with dbmPropagationMode full', () => { diff --git a/packages/dd-trace/src/plugins/database.js b/packages/dd-trace/src/plugins/database.js index 1328b98f46a..cd688133761 100644 --- a/packages/dd-trace/src/plugins/database.js +++ b/packages/dd-trace/src/plugins/database.js @@ -92,27 +92,6 @@ class DatabasePlugin extends StoragePlugin { return `/*${dbmTraceComment}*/ ${query}` } - injectDbmCommand (span, command, serviceName) { - const dbmTraceComment = this.createDbmComment(span, serviceName) - - if (!dbmTraceComment) { - return command - } - - if (command.comment) { - // if the command already has a comment, append the dbm trace comment - if (typeof command.comment === 'string') { - command.comment += `,${dbmTraceComment}` - } else if (Array.isArray(command.comment)) { - command.comment.push(dbmTraceComment) - } // do nothing if the comment is not a string or an array - } else { - command.comment = dbmTraceComment - } - - return command - } - maybeTruncate (query) { const maxLength = typeof this.config.truncate === 'number' ? this.config.truncate From 7d5b6db6554a9c8db00a65c5a7165f5c35d6f23f Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Wed, 12 Feb 2025 22:24:55 +0000 Subject: [PATCH 15/17] add tests to verify command with comments --- .../test/core.spec.js | 62 ++++++++++++++++++ .../test/mongodb.spec.js | 65 ------------------- 2 files changed, 62 insertions(+), 65 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/test/core.spec.js b/packages/datadog-plugin-mongodb-core/test/core.spec.js index 322345c991e..771c809beef 100644 --- a/packages/datadog-plugin-mongodb-core/test/core.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/core.spec.js @@ -456,6 +456,68 @@ describe('Plugin', () => { server.insert(`test.${collection}`, [{ a: 1 }], () => {}) }) + + it('DBM propagation should inject service mode after eixsting str comment', done => { + agent + .use(traces => { + const span = traces[0][0] + + expect(injectDbmCommandSpy.called).to.be.true + const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue + expect(instrumentedCommand).to.have.property('comment') + expect(instrumentedCommand.comment).to.equal( + `test comment,` + + `dddb='${encodeURIComponent(span.meta['db.name'])}',` + + 'dddbs=\'test-mongodb\',' + + 'dde=\'tester\',' + + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + + `ddps='${encodeURIComponent(span.meta.service)}',` + + `ddpv='${ddpv}',` + + `ddprs='${encodeURIComponent(span.meta['peer.service'])}'` + ) + }) + .then(done) + .catch(done) + + server.command(`test.${collection}`, { + find: `test.${collection}`, + query: { + _id: Buffer.from('1234') + }, + comment: "test comment" + }, () => {}) + }) + + it('DBM propagation should inject service mode after eixsting array comment', done => { + agent + .use(traces => { + const span = traces[0][0] + + expect(injectDbmCommandSpy.called).to.be.true + const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue + expect(instrumentedCommand).to.have.property('comment') + expect(instrumentedCommand.comment).to.deep.equal([ + `test comment`, + `dddb='${encodeURIComponent(span.meta['db.name'])}',` + + 'dddbs=\'test-mongodb\',' + + 'dde=\'tester\',' + + `ddh='${encodeURIComponent(span.meta['out.host'])}',` + + `ddps='${encodeURIComponent(span.meta.service)}',` + + `ddpv='${ddpv}',` + + `ddprs='${encodeURIComponent(span.meta['peer.service'])}'` + ]) + }) + .then(done) + .catch(done) + + server.command(`test.${collection}`, { + find: `test.${collection}`, + query: { + _id: Buffer.from('1234') + }, + comment: ["test comment"] + }, () => {}) + }) }) describe('with dbmPropagationMode full', () => { diff --git a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js index baee2862628..db6ee8ffeec 100644 --- a/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/mongodb.spec.js @@ -388,71 +388,6 @@ describe('Plugin', () => { _id: Buffer.from('1234') }).toArray() }) - - it('should append DBM propagation to existing str comment', done => { - agent - .use(traces => { - const span = traces[0][0] - - expect(injectDbmCommandSpy.called).to.be.true - const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue - expect(instrumentedCommand).to.have.property('comment') - expect(instrumentedCommand.comment).to.equal( - 'find test,' + - `dddb='${encodeURIComponent(span.meta['db.name'])}',` + - 'dddbs=\'test-mongodb\',' + - 'dde=\'tester\',' + - `ddh='${encodeURIComponent(span.meta['out.host'])}',` + - `ddps='${encodeURIComponent(span.meta.service)}',` + - `ddpv='${ddpv}',` + - `ddprs='${encodeURIComponent(span.meta['peer.service'])}'` - ) - }) - .then(done) - .catch(done) - - collection.find( - { - _id: Buffer.from('1234') - }, - { - comment: 'find test' - } - ).toArray() - }) - - it('should append DBM propagation to existing array comment', done => { - agent - .use(traces => { - const span = traces[0][0] - - expect(injectDbmCommandSpy.called).to.be.true - const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue - expect(instrumentedCommand).to.have.property('comment') - expect(instrumentedCommand.comment).to.be.an('array') - expect(instrumentedCommand.comment).to.equal([ - 'find test', - `dddb='${encodeURIComponent(span.meta['db.name'])}',` + - 'dddbs=\'test-mongodb\',' + - 'dde=\'tester\',' + - `ddh='${encodeURIComponent(span.meta['out.host'])}',` + - `ddps='${encodeURIComponent(span.meta.service)}',` + - `ddpv='${ddpv}',` + - `ddprs='${encodeURIComponent(span.meta['peer.service'])}'` - ]) - }) - .then(done) - .catch(done) - - collection.find( - { - _id: Buffer.from('1234') - }, - { - comment: ['find test'] - } - ).toArray() - }) }) describe('with dbmPropagationMode full', () => { From 470722f7489095dd7c007024a427dc81ae192ae4 Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Wed, 12 Feb 2025 22:33:37 +0000 Subject: [PATCH 16/17] fix lint --- .../test/core.spec.js | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/datadog-plugin-mongodb-core/test/core.spec.js b/packages/datadog-plugin-mongodb-core/test/core.spec.js index 771c809beef..98b483d79aa 100644 --- a/packages/datadog-plugin-mongodb-core/test/core.spec.js +++ b/packages/datadog-plugin-mongodb-core/test/core.spec.js @@ -466,7 +466,7 @@ describe('Plugin', () => { const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue expect(instrumentedCommand).to.have.property('comment') expect(instrumentedCommand.comment).to.equal( - `test comment,` + + 'test comment,' + `dddb='${encodeURIComponent(span.meta['db.name'])}',` + 'dddbs=\'test-mongodb\',' + 'dde=\'tester\',' + @@ -479,13 +479,13 @@ describe('Plugin', () => { .then(done) .catch(done) - server.command(`test.${collection}`, { - find: `test.${collection}`, - query: { - _id: Buffer.from('1234') - }, - comment: "test comment" - }, () => {}) + server.command(`test.${collection}`, { + find: `test.${collection}`, + query: { + _id: Buffer.from('1234') + }, + comment: 'test comment' + }, () => {}) }) it('DBM propagation should inject service mode after eixsting array comment', done => { @@ -497,7 +497,7 @@ describe('Plugin', () => { const instrumentedCommand = injectDbmCommandSpy.getCall(0).returnValue expect(instrumentedCommand).to.have.property('comment') expect(instrumentedCommand.comment).to.deep.equal([ - `test comment`, + 'test comment', `dddb='${encodeURIComponent(span.meta['db.name'])}',` + 'dddbs=\'test-mongodb\',' + 'dde=\'tester\',' + @@ -510,13 +510,13 @@ describe('Plugin', () => { .then(done) .catch(done) - server.command(`test.${collection}`, { - find: `test.${collection}`, - query: { - _id: Buffer.from('1234') - }, - comment: ["test comment"] - }, () => {}) + server.command(`test.${collection}`, { + find: `test.${collection}`, + query: { + _id: Buffer.from('1234') + }, + comment: ['test comment'] + }, () => {}) }) }) From 5f8d92d35833f2ac921667cd54a09176c8542743 Mon Sep 17 00:00:00 2001 From: Zhengda Lu Date: Fri, 14 Feb 2025 11:59:19 -0500 Subject: [PATCH 17/17] Update index.js Co-authored-by: Thomas Hunter II --- packages/datadog-plugin-mongodb-core/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/datadog-plugin-mongodb-core/src/index.js b/packages/datadog-plugin-mongodb-core/src/index.js index f4e4d94a82d..a60182458e1 100644 --- a/packages/datadog-plugin-mongodb-core/src/index.js +++ b/packages/datadog-plugin-mongodb-core/src/index.js @@ -51,7 +51,7 @@ class MongodbCorePlugin extends DatabasePlugin { // if the command already has a comment, append the dbm trace comment if (typeof dbmTracedCommand.comment === 'string') { dbmTracedCommand.comment += `,${dbmTraceComment}` - } else if (Array.isArray(command.comment)) { + } else if (Array.isArray(dbmTracedCommand.comment)) { dbmTracedCommand.comment.push(dbmTraceComment) } // do nothing if the comment is not a string or an array } else {