From 18e815ffc66a5840059a69a1676d92a750433113 Mon Sep 17 00:00:00 2001 From: Onur Temizkan Date: Fri, 17 Jan 2025 00:18:51 +0000 Subject: [PATCH 1/8] feat(instrumentation-mongodb): Add `requireParentSpan` config option. --- .../README.md | 1 + .../src/instrumentation.ts | 38 ++++++++++++++++--- .../src/types.ts | 5 +++ .../test/mongodb-v5-v6.test.ts | 36 ++++++++++++++++++ 4 files changed, 75 insertions(+), 5 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/README.md b/plugins/node/opentelemetry-instrumentation-mongodb/README.md index ca43f4e3bd..2aba6a5bd6 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/README.md +++ b/plugins/node/opentelemetry-instrumentation-mongodb/README.md @@ -54,6 +54,7 @@ Mongodb instrumentation has few options available to choose from. You can set th | [`enhancedDatabaseReporting`](./src/types.ts#L32) | `string` | If true, additional information about query parameters and results will be attached (as `attributes`) to spans representing database operations | | `responseHook` | `MongoDBInstrumentationExecutionResponseHook` (function) | Function for adding custom attributes from db response | | `dbStatementSerializer` | `DbStatementSerializer` (function) | Custom serializer function for the db.statement tag | +| `requireParentSpan` | `boolean` | Require a parent span in order to create mongodb spans, default when unset is `true` | ## Semantic Conventions diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts index caaff5c550..7e6dc713e4 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts @@ -55,13 +55,21 @@ import { V4Connect, V4Session } from './internal-types'; import { PACKAGE_NAME, PACKAGE_VERSION } from './version'; import { UpDownCounter } from '@opentelemetry/api'; +const DEFAULT_CONFIG: MongoDBInstrumentationConfig = { + requireParentSpan: true, +}; + /** mongodb instrumentation plugin for OpenTelemetry */ export class MongoDBInstrumentation extends InstrumentationBase { private _connectionsUsage!: UpDownCounter; private _poolName!: string; constructor(config: MongoDBInstrumentationConfig = {}) { - super(PACKAGE_NAME, PACKAGE_VERSION, config); + super(PACKAGE_NAME, PACKAGE_VERSION, { ...DEFAULT_CONFIG, ...config }); + } + + override setConfig(config: MongoDBInstrumentationConfig = {}) { + super.setConfig({ ...DEFAULT_CONFIG, ...config }); } override _updateMetricInstruments() { @@ -438,10 +446,15 @@ export class MongoDBInstrumentation extends InstrumentationBase { }); }); + describe('requireParentSpan', () => { + it('should create spans without parent span when requireParentSpan is false', done => { + create({ + requireParentSpan: false, + }); + + collection + .insertOne({ a: 1 }) + .then(() => { + assert.strictEqual(getTestSpans().length, 1); + done(); + }) + .catch(err => { + done(err); + }); + }); + + it('should not create spans without parent span when requireParentSpan is set to false by setConfig', done => { + create(); + + instrumentation.setConfig({ + requireParentSpan: false, + }); + + collection + .insertOne({ a: 1 }) + .then(() => { + assert.strictEqual(getTestSpans().length, 1); + done(); + }) + .catch(err => { + done(err); + }); + }); + }) + /** Should intercept command */ describe('Removing Instrumentation', () => { it('should unpatch plugin', () => { From e1ee9b63dce89c6f8a257c9389e5d65c4e87da04 Mon Sep 17 00:00:00 2001 From: Onur Temizkan Date: Fri, 17 Jan 2025 00:29:32 +0000 Subject: [PATCH 2/8] Lint and add a `true` test case. --- .../src/instrumentation.ts | 12 +++++++---- .../test/mongodb-v5-v6.test.ts | 20 +++++++++++++++++-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts index 7e6dc713e4..8ed5989008 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts @@ -449,7 +449,8 @@ export class MongoDBInstrumentation extends InstrumentationBase { }); describe('requireParentSpan', () => { + it('should not create spans without parent span when requireParentSpan is explicitly set to true', done => { + create({ + requireParentSpan: true, + }); + + collection + .insertOne({ a: 1 }) + .then(() => { + assert.strictEqual(getTestSpans().length, 0); + done(); + }) + .catch(err => { + done(err); + }); + }); + it('should create spans without parent span when requireParentSpan is false', done => { create({ requireParentSpan: false, @@ -669,7 +685,7 @@ describe('MongoDBInstrumentation-Tracing-v5', () => { }); }); - it('should not create spans without parent span when requireParentSpan is set to false by setConfig', done => { + it('should create spans without parent span when requireParentSpan is set to false by setConfig', done => { create(); instrumentation.setConfig({ @@ -686,7 +702,7 @@ describe('MongoDBInstrumentation-Tracing-v5', () => { done(err); }); }); - }) + }); /** Should intercept command */ describe('Removing Instrumentation', () => { From b3a640209cf8fcbbb4f6460661800cbfc9debef4 Mon Sep 17 00:00:00 2001 From: Onur Temizkan Date: Fri, 17 Jan 2025 00:35:22 +0000 Subject: [PATCH 3/8] Reset behaviour to avoid flakes in other tests. --- .../test/mongodb-v5-v6.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts index 47e57b4fb5..5eb2c6f88b 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts @@ -653,6 +653,13 @@ describe('MongoDBInstrumentation-Tracing-v5', () => { }); describe('requireParentSpan', () => { + // Resetting the behavior to default to avoid flakes in other tests + afterEach(() => { + instrumentation.setConfig({ + requireParentSpan: true, + }); + }); + it('should not create spans without parent span when requireParentSpan is explicitly set to true', done => { create({ requireParentSpan: true, From 5d7f5c165d5f0c4bb156c873f1f7aae61f811471 Mon Sep 17 00:00:00 2001 From: Onur Temizkan Date: Wed, 22 Jan 2025 13:55:05 +0000 Subject: [PATCH 4/8] Refactor --- .../src/instrumentation.ts | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts index 8ed5989008..dc35acd533 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts @@ -446,11 +446,8 @@ export class MongoDBInstrumentation extends InstrumentationBase undefined; - if (typeof cmd !== 'object' || cmd.ismaster || cmd.hello) { + if ( + skipInstrumentation || + typeof cmd !== 'object' || + cmd.ismaster || + cmd.hello + ) { return original.apply(this, args); } @@ -654,12 +659,8 @@ export class MongoDBInstrumentation extends InstrumentationBase Date: Thu, 23 Jan 2025 12:56:55 +0000 Subject: [PATCH 5/8] Update command span creation behaviour. --- .../src/instrumentation.ts | 26 +++---- .../test/mongodb-v5-v6.test.ts | 69 +++++++------------ 2 files changed, 37 insertions(+), 58 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts index dc35acd533..b627a3d0be 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts @@ -462,6 +462,7 @@ export class MongoDBInstrumentation extends InstrumentationBase undefined; - if ( - skipInstrumentation || - typeof cmd !== 'object' || - cmd.ismaster || - cmd.hello - ) { + if (typeof cmd !== 'object' || cmd.ismaster || cmd.hello) { return original.apply(this, args); } let span = undefined; - if (currentSpan) { + if (!skipInstrumentation) { span = instrumentation.tracer.startSpan(`mongodb.${commandType}`, { kind: SpanKind.CLIENT, }); @@ -663,6 +655,7 @@ export class MongoDBInstrumentation extends InstrumentationBase { describe('requireParentSpan', () => { // Resetting the behavior to default to avoid flakes in other tests - afterEach(() => { - instrumentation.setConfig({ - requireParentSpan: true, - }); + beforeEach(() => { + instrumentation.setConfig(); }); it('should not create spans without parent span when requireParentSpan is explicitly set to true', done => { - create({ - requireParentSpan: true, + context.with(trace.deleteSpan(context.active()), () => { + collection + .insertOne({ a: 1 }) + .then(() => { + assert.strictEqual(getTestSpans().length, 0); + done(); + }) + .catch(err => { + done(err); + }); }); - - collection - .insertOne({ a: 1 }) - .then(() => { - assert.strictEqual(getTestSpans().length, 0); - done(); - }) - .catch(err => { - done(err); - }); }); it('should create spans without parent span when requireParentSpan is false', done => { - create({ - requireParentSpan: false, - }); - - collection - .insertOne({ a: 1 }) - .then(() => { - assert.strictEqual(getTestSpans().length, 1); - done(); - }) - .catch(err => { - done(err); - }); - }); - - it('should create spans without parent span when requireParentSpan is set to false by setConfig', done => { - create(); - instrumentation.setConfig({ requireParentSpan: false, }); - collection - .insertOne({ a: 1 }) - .then(() => { - assert.strictEqual(getTestSpans().length, 1); - done(); - }) - .catch(err => { - done(err); - }); + context.with(trace.deleteSpan(context.active()), () => { + collection + .insertOne({ a: 1 }) + .then(() => { + assert.strictEqual(getTestSpans().length, 1); + done(); + }) + .catch(err => { + done(err); + }); + }); }); }); @@ -731,6 +711,9 @@ describe('MongoDBInstrumentation-Tracing-v5', () => { }) .catch(err => { done(err); + }) + .finally(() => { + span.end(); }); }); From 6d1bf9a59931f6f63f2fe3c5f5432269dd04aea1 Mon Sep 17 00:00:00 2001 From: Onur Temizkan Date: Mon, 27 Jan 2025 15:50:05 +0000 Subject: [PATCH 6/8] Add mongodb 4 tests. --- .../test/mongodb-v4.test.ts | 43 +++++++++++++++++++ .../test/mongodb-v5-v6.test.ts | 7 +-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4.test.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4.test.ts index febd901776..eec56fe5f4 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4.test.ts @@ -639,6 +639,49 @@ describe('MongoDBInstrumentation-Tracing-v4', () => { }); }); + describe('requireParentSpan', () => { + // Resetting the behavior to default to avoid flakes in other tests + beforeEach(() => { + instrumentation.setConfig(); + }); + + afterEach(() => { + instrumentation.setConfig(); + }); + + it('should not create spans without parent span when requireParentSpan is explicitly set to true', done => { + context.with(trace.deleteSpan(context.active()), () => { + collection + .insertOne({ a: 1 }) + .then(() => { + assert.strictEqual(getTestSpans().length, 0); + done(); + }) + .catch(err => { + done(err); + }); + }); + }); + + it('should create spans without parent span when requireParentSpan is false', done => { + instrumentation.setConfig({ + requireParentSpan: false, + }); + + context.with(trace.deleteSpan(context.active()), () => { + collection + .insertOne({ a: 1 }) + .then(() => { + assert.strictEqual(getTestSpans().length, 1); + done(); + }) + .catch(err => { + done(err); + }); + }); + }); + }); + /** Should intercept command */ describe('Removing Instrumentation', () => { it('should unpatch plugin', () => { diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts index fb3fa4f271..18a35474ac 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts @@ -658,6 +658,10 @@ describe('MongoDBInstrumentation-Tracing-v5', () => { instrumentation.setConfig(); }); + afterEach(() => { + instrumentation.setConfig(); + }); + it('should not create spans without parent span when requireParentSpan is explicitly set to true', done => { context.with(trace.deleteSpan(context.active()), () => { collection @@ -712,9 +716,6 @@ describe('MongoDBInstrumentation-Tracing-v5', () => { .catch(err => { done(err); }) - .finally(() => { - span.end(); - }); }); it('should not create a child span for cursor', done => { From ff03fc3968698687abdf48f072e2a36468a949fb Mon Sep 17 00:00:00 2001 From: Onur Temizkan Date: Mon, 27 Jan 2025 15:58:39 +0000 Subject: [PATCH 7/8] Lint --- .../test/mongodb-v5-v6.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts index 18a35474ac..33ae1e1e5c 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts @@ -715,7 +715,7 @@ describe('MongoDBInstrumentation-Tracing-v5', () => { }) .catch(err => { done(err); - }) + }); }); it('should not create a child span for cursor', done => { From 90a9dcc3c6192ecee652e7de9dbb54b3698baad4 Mon Sep 17 00:00:00 2001 From: Onur Temizkan Date: Mon, 27 Jan 2025 16:21:43 +0000 Subject: [PATCH 8/8] Add mongodb v3 tests --- .../test/mongodb-v3.test.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v3.test.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v3.test.ts index 4a3bd9a6e0..3f6ee8e44c 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v3.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v3.test.ts @@ -669,6 +669,49 @@ describe('MongoDBInstrumentation-Tracing-v3', () => { }); }); + describe('requireParentSpan', () => { + // Resetting the behavior to default to avoid flakes in other tests + beforeEach(() => { + instrumentation.setConfig(); + }); + + afterEach(() => { + instrumentation.setConfig(); + }); + + it('should not create spans without parent span when requireParentSpan is explicitly set to true', done => { + context.with(trace.deleteSpan(context.active()), () => { + collection + .insertOne({ a: 1 }) + .then(() => { + assert.strictEqual(getTestSpans().length, 0); + done(); + }) + .catch(err => { + done(err); + }); + }); + }); + + it('should create spans without parent span when requireParentSpan is false', done => { + instrumentation.setConfig({ + requireParentSpan: false, + }); + + context.with(trace.deleteSpan(context.active()), () => { + collection + .insertOne({ a: 1 }) + .then(() => { + assert.strictEqual(getTestSpans().length, 1); + done(); + }) + .catch(err => { + done(err); + }); + }); + }); + }); + /** Should intercept command */ describe('Removing Instrumentation', () => { it('should unpatch plugin', () => {