Skip to content

Commit 1c4ccb4

Browse files
committed
feat(instrumentation-mongodb): Lighten scrubbed data
1 parent 6b4e532 commit 1c4ccb4

File tree

2 files changed

+112
-6
lines changed

2 files changed

+112
-6
lines changed

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

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,25 @@ import { V4Connect, V4Session } from './internal-types';
5555
import { PACKAGE_NAME, PACKAGE_VERSION } from './version';
5656
import { UpDownCounter } from '@opentelemetry/api';
5757

58+
// Skipping mongoose-added `non-enumerable` properties
59+
// https://github.com/Automattic/mongoose/blob/b34aba65bd64540e330665477f542eb79c877909/lib/helpers/document/compile.js#L217C11-L228C6
60+
// These properties are added by mongoose and supposed to be non-enumerable
61+
// but they are enumerable in some versions of mongoose.
62+
// These properties have made non-enumerable from [email protected]
63+
// https://github.com/Automattic/mongoose/commit/62b7b9c07ad3c763d5e42714ee149c28412db79e
64+
const KEYS_TO_SKIP_SCRUBBING = [
65+
'isNew',
66+
'$__',
67+
'$errors',
68+
'errors',
69+
'_doc',
70+
'$locals',
71+
'$op',
72+
'__parentArray',
73+
'__index',
74+
'$isDocumentArrayElement',
75+
];
76+
5877
/** mongodb instrumentation plugin for OpenTelemetry */
5978
export class MongoDBInstrumentation extends InstrumentationBase<MongoDBInstrumentationConfig> {
6079
private _connectionsUsage!: UpDownCounter;
@@ -932,17 +951,29 @@ export class MongoDBInstrumentation extends InstrumentationBase<MongoDBInstrumen
932951
return JSON.stringify(resultObj);
933952
}
934953

935-
private _scrubStatement(value: unknown): unknown {
954+
private _scrubStatement(value: unknown, depth = 0): unknown {
955+
if (depth >= 10) {
956+
return 'Max Depth';
957+
}
958+
959+
if (value instanceof Uint8Array || value instanceof Buffer) {
960+
return 'Binary Data';
961+
}
962+
936963
if (Array.isArray(value)) {
937-
return value.map(element => this._scrubStatement(element));
964+
return value.map(element => this._scrubStatement(element, depth + 1));
938965
}
939966

940967
if (typeof value === 'object' && value !== null) {
941968
return Object.fromEntries(
942-
Object.entries(value).map(([key, element]) => [
943-
key,
944-
this._scrubStatement(element),
945-
])
969+
Object.entries(value)
970+
.filter(([key]) => {
971+
return !KEYS_TO_SKIP_SCRUBBING.includes(key);
972+
})
973+
.map(([key, element]) => [
974+
key,
975+
this._scrubStatement(element, depth + 1),
976+
])
946977
);
947978
}
948979

plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,81 @@ describe('MongoDBInstrumentation-Tracing-v5', () => {
415415
});
416416
});
417417
});
418+
419+
it('should skip `Buffer` and `Uint8Array` values', done => {
420+
const buffer = Buffer.from('buffer');
421+
const uint8Array = new Uint8Array([1, 2, 3, 4]);
422+
const span = trace.getTracer('default').startSpan('insertRootSpan');
423+
context.with(trace.setSpan(context.active(), span), () => {
424+
collection
425+
.insertOne({ buffer, uint8Array })
426+
.then(() => {
427+
span.end();
428+
const spans = getTestSpans();
429+
const operationName = 'mongodb.insert';
430+
assertSpans(
431+
spans,
432+
operationName,
433+
SpanKind.CLIENT,
434+
'insert',
435+
URL,
436+
false,
437+
false
438+
);
439+
const mongoSpan = spans.find(s => s.name === operationName);
440+
const dbStatement = JSON.parse(
441+
mongoSpan!.attributes[SEMATTRS_DB_STATEMENT] as string
442+
);
443+
assert.strictEqual(dbStatement.buffer, 'Binary Data');
444+
assert.strictEqual(dbStatement.uint8Array, 'Binary Data');
445+
done();
446+
})
447+
.catch(err => {
448+
done(err);
449+
});
450+
});
451+
});
452+
453+
it('should skip nested levels of objects over the limit of 10', done => {
454+
const deeplyNestedObject = {
455+
a: {
456+
b: { c: { d: { e: { f: { g: { h: { i: { j: { k: 1 } } } } } } } } },
457+
},
458+
};
459+
460+
const span = trace.getTracer('default').startSpan('insertRootSpan');
461+
context.with(trace.setSpan(context.active(), span), () => {
462+
collection
463+
.insertOne({ deeplyNestedObject })
464+
.then(() => {
465+
span.end();
466+
const spans = getTestSpans();
467+
const operationName = 'mongodb.insert';
468+
assertSpans(
469+
spans,
470+
operationName,
471+
SpanKind.CLIENT,
472+
'insert',
473+
URL,
474+
false,
475+
false
476+
);
477+
const mongoSpan = spans.find(s => s.name === operationName);
478+
const dbStatement = JSON.parse(
479+
mongoSpan!.attributes[SEMATTRS_DB_STATEMENT] as string
480+
);
481+
assert.deepStrictEqual(dbStatement.deeplyNestedObject, {
482+
a: {
483+
b: { c: { d: { e: { f: { g: { h: { i: 'Max Depth' } } } } } } },
484+
},
485+
});
486+
done();
487+
})
488+
.catch(err => {
489+
done(err);
490+
});
491+
});
492+
});
418493
});
419494

420495
describe('when specifying a dbStatementSerializer configuration', () => {

0 commit comments

Comments
 (0)