Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(instrumentation-mongodb): Add requireParentSpan config option. #2658

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,21 @@
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<MongoDBInstrumentationConfig> {
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() {
Expand Down Expand Up @@ -438,10 +446,13 @@
callback?: Function
) {
const currentSpan = trace.getSpan(context.active());
const skipInstrumentation =
instrumentation._checkSkipInstrumentation(currentSpan);

Check warning on line 450 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L450

Added line #L450 was not covered by tests

const resultHandler =
typeof options === 'function' ? options : callback;
if (
!currentSpan ||
skipInstrumentation ||

Check warning on line 455 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L455

Added line #L455 was not covered by tests
typeof resultHandler !== 'function' ||
typeof ops !== 'object'
) {
Expand All @@ -451,6 +462,7 @@
return original.call(this, server, ns, ops, options, callback);
}
}

const span = instrumentation.tracer.startSpan(
`mongodb.${operationName}`,
{
Expand Down Expand Up @@ -490,10 +502,14 @@
callback?: Function
) {
const currentSpan = trace.getSpan(context.active());
const skipInstrumentation =
instrumentation._checkSkipInstrumentation(currentSpan);

Check warning on line 506 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L506

Added line #L506 was not covered by tests

const resultHandler =
typeof options === 'function' ? options : callback;

if (
!currentSpan ||
skipInstrumentation ||

Check warning on line 512 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L512

Added line #L512 was not covered by tests
typeof resultHandler !== 'function' ||
typeof cmd !== 'object'
) {
Expand All @@ -503,6 +519,7 @@
return original.call(this, server, ns, cmd, options, callback);
}
}

const commandType = MongoDBInstrumentation._getCommandType(cmd);
const type =
commandType === MongodbCommandType.UNKNOWN ? 'command' : commandType;
Expand Down Expand Up @@ -535,20 +552,17 @@
callback: any
) {
const currentSpan = trace.getSpan(context.active());
const skipInstrumentation =
instrumentation._checkSkipInstrumentation(currentSpan);

Check warning on line 556 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L556

Added line #L556 was not covered by tests
const resultHandler = callback;
const commandType = Object.keys(cmd)[0];

if (
typeof resultHandler !== 'function' ||
typeof cmd !== 'object' ||
cmd.ismaster ||
cmd.hello
) {
if (typeof cmd !== 'object' || cmd.ismaster || cmd.hello) {

Check warning on line 560 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L560

Added line #L560 was not covered by tests
return original.call(this, ns, cmd, options, callback);
}

let span = undefined;
if (currentSpan) {
if (!skipInstrumentation) {

Check warning on line 565 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L565

Added line #L565 was not covered by tests
span = instrumentation.tracer.startSpan(`mongodb.${commandType}`, {
kind: SpanKind.CLIENT,
});
Expand Down Expand Up @@ -581,6 +595,9 @@
) {
const [ns, cmd] = args;
const currentSpan = trace.getSpan(context.active());
const skipInstrumentation =
instrumentation._checkSkipInstrumentation(currentSpan);

const commandType = Object.keys(cmd)[0];
const resultHandler = () => undefined;

Expand All @@ -589,7 +606,7 @@
}

let span = undefined;
if (currentSpan) {
if (!skipInstrumentation) {
span = instrumentation.tracer.startSpan(`mongodb.${commandType}`, {
kind: SpanKind.CLIENT,
});
Expand Down Expand Up @@ -634,10 +651,13 @@
callback?: Function
) {
const currentSpan = trace.getSpan(context.active());
const skipInstrumentation =
instrumentation._checkSkipInstrumentation(currentSpan);

Check warning on line 655 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L655

Added line #L655 was not covered by tests
const resultHandler =
typeof options === 'function' ? options : callback;

if (
!currentSpan ||
skipInstrumentation ||

Check warning on line 660 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L660

Added line #L660 was not covered by tests
typeof resultHandler !== 'function' ||
typeof cmd !== 'object'
) {
Expand All @@ -655,6 +675,7 @@
);
}
}

const span = instrumentation.tracer.startSpan('mongodb.find', {
kind: SpanKind.CLIENT,
});
Expand Down Expand Up @@ -699,9 +720,13 @@
callback?: Function
) {
const currentSpan = trace.getSpan(context.active());
const skipInstrumentation =
instrumentation._checkSkipInstrumentation(currentSpan);

Check warning on line 724 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L724

Added line #L724 was not covered by tests

const resultHandler =
typeof options === 'function' ? options : callback;
if (!currentSpan || typeof resultHandler !== 'function') {

if (skipInstrumentation || typeof resultHandler !== 'function') {

Check warning on line 729 in plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts

View check run for this annotation

Codecov / codecov/patch

plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts#L729

Added line #L729 was not covered by tests
if (typeof options === 'function') {
return original.call(
this,
Expand All @@ -723,6 +748,7 @@
);
}
}

const span = instrumentation.tracer.startSpan('mongodb.getMore', {
kind: SpanKind.CLIENT,
});
Expand Down Expand Up @@ -1021,4 +1047,10 @@
const poolName = `mongodb://${host}:${port}/${database}`;
this._poolName = poolName;
}

private _checkSkipInstrumentation(currentSpan: Span | undefined) {
const requireParentSpan = this.getConfig().requireParentSpan;
const hasNoParentSpan = currentSpan === undefined;
return requireParentSpan === true && hasNoParentSpan;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ export interface MongoDBInstrumentationConfig extends InstrumentationConfig {
* Custom serializer function for the db.statement tag
*/
dbStatementSerializer?: DbStatementSerializer;

/**
* Require parent to create mongodb span, default when unset is true
*/
requireParentSpan?: boolean;
}

export interface MongoResponseHookInformation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,45 @@ describe('MongoDBInstrumentation-Tracing-v5', () => {
});
});

describe('requireParentSpan', () => {
// Resetting the behavior to default to avoid flakes in other tests
beforeEach(() => {
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', () => {
Expand All @@ -672,6 +711,9 @@ describe('MongoDBInstrumentation-Tracing-v5', () => {
})
.catch(err => {
done(err);
})
.finally(() => {
span.end();
});
});

Expand Down
Loading